加入收藏 | 设为首页 | 会员中心 | 我要投稿 大同站长网 (https://www.0352zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

使用POSIX线程处理“生产者/消费者”问题

发布时间:2021-11-25 16:00:31 所属栏目:教程 来源:互联网
导读:使用POSIX线程解决生产者/消费者问题: /* * File : pc.cpp * * Title : Demo Producer/Consumer. * * Short : A solution to the producer consumer problem using pthreads. * This is a simple FIFO pipe between two tasks. The primary problem is * en

使用POSIX线程解决“生产者/消费者”问题:
 
/*
*   File    : pc.cpp
*
*   Title   : Demo Producer/Consumer.
*
*   Short   : A solution to the producer consumer problem using pthreads.
*           This is a simple FIFO pipe between two tasks. The primary problem is
*           ensuring that the producer blocks if the FIFO is full, and the consumer
*           blocks if it is empty, and avoiding data-races along the way. A secondary
*           concern is that there is as little interference between the two tasks as
*           possible.  
*
*   Author  : Andrae Muys
*
*   Date    : 18 September 1997
*/  
  
#include <stdlib.h>   
#include <pthread.h>   
#include <assert.h>   
  
#ifdef _WIN32   
#   include <windows.h>   
#   define SLEEP(ms) Sleep(ms)   
#elif defined(LINUX)   
#   include <unistd.h>   
#   define SLEEP(ms) sleep(ms)   
#endif   
  
#define QUEUE_SIZE  10   
#define LOOP        20   
  
void* producer (void *args);  
void* consumer (void *args);  
  
typedef struct  
{  
    int buf[QUEUE_SIZE];  
    long head, tail;  
    bool full, empty;  
    pthread_mutex_t *mutex;  
    pthread_cond_t *notFull, *notEmpty;  
} Queue;  
  
Queue*  queueInit (void);  
void    queueDelete (Queue *q);  
void    queueAdd (Queue *q, int in);  
void    queueDel (Queue *q, int *out);  
  
int main(int argc, char* argv[])  
{  
    Queue* fifo = queueInit ();  
    assert(fifo !=  NULL);  
  
    pthread_t pro, con;  
    pthread_create (&pro, NULL, &producer, fifo);  
    pthread_create (&con, NULL, &consumer, fifo);  
    pthread_join (pro, NULL);  
    pthread_join (con, NULL);  
    queueDelete (fifo);  
    return 0;  
}  
  
void* producer (void *q)  
{  
    Queue* fifo = (Queue *)q;  
  
    for (int i = 0; i < LOOP; i++)  
    {  
        // 临界区操作:若队列未满,添加新数据   
        pthread_mutex_lock (fifo->mutex);  
        while (fifo->full)  
        {  
            printf ("producer: Queue FULL.n");  
            pthread_cond_wait (fifo->notFull, fifo->mutex);  
        }  
        queueAdd (fifo, i);  
        pthread_mutex_unlock (fifo->mutex);  
  
        // 数据添加结束,发“队列有数据”信号   
        pthread_cond_signal (fifo->notEmpty);  
        SLEEP (100);  
    }  
  
    // 与上面类似   
    for (int i = 0; i < LOOP; i++)  
    {  
        pthread_mutex_lock (fifo->mutex);  
        while (fifo->full)  
        {  
            printf ("producer: Queue FULL.n");  
            pthread_cond_wait (fifo->notFull, fifo->mutex);  
        }  
        queueAdd (fifo, i);  
        pthread_mutex_unlock (fifo->mutex);  
        pthread_cond_signal (fifo->notEmpty);  
        SLEEP (200);  
    }  
    return (NULL);  
}  
  
void* consumer (void *q)  
{  
    int d;  
  
    Queue *fifo = (Queue *)q;  
  
    for (int i = 0; i < LOOP; i++)  
    {  
        // 临界区操作:若队列不空,则取出数据   
        pthread_mutex_lock (fifo->mutex);  
        while (fifo->empty)  
        {  
            printf ("consumer: Queue EMPTY.n");  
            pthread_cond_wait (fifo->notEmpty, fifo->mutex);  
        }  
        queueDel (fifo, &d);  
        pthread_mutex_unlock (fifo->mutex);  
  
        // 取完数据,发“队列不满”信号   
        pthread_cond_signal (fifo->notFull);  
        printf ("consumer: recieved %d.n", d);  
        SLEEP(200);  
    }  
  
    // 与上面类似   
    for (int i = 0; i < LOOP; i++)  
    {  
        pthread_mutex_lock (fifo->mutex);  
        while (fifo->empty)  
        {  
            printf ("consumer: Queue EMPTY.n");  
            pthread_cond_wait (fifo->notEmpty, fifo->mutex);  
        }  
        queueDel (fifo, &d);  
        pthread_mutex_unlock (fifo->mutex);  
        pthread_cond_signal (fifo->notFull);  
        printf ("consumer: recieved %d.n", d);  
        SLEEP (50);  
    }  
    return (NULL);  
}  
  
Queue *queueInit (void)  
{  
    Queue *q = (Queue *)malloc (sizeof (Queue));  
    if (q == NULL) return (NULL);  
  
    q->empty = true;  
    q->full = false;  
    q->head = 0;  
    q->tail = 0;  
  
    q->mutex = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));  
    pthread_mutex_init (q->mutex, NULL);  
    q->notFull = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));  
    pthread_cond_init (q->notFull, NULL);  
    q->notEmpty = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));  
    pthread_cond_init (q->notEmpty, NULL);  
      
    return (q);  
}  
  
void queueDelete (Queue *q)  
{  
    pthread_mutex_destroy (q->mutex);  
    free (q->mutex);   
  
    pthread_cond_destroy (q->notFull);  
    free (q->notFull);  
  
    pthread_cond_destroy (q->notEmpty);  
    free (q->notEmpty);  
  
    free (q);  
}  
  
void queueAdd (Queue *q, int in)  
{  
    q->buf[q->tail] = in;  
    q->tail++;  
    if (q->tail == QUEUE_SIZE)   // 循环队列   
        q->tail = 0;  
  
    if (q->tail == q->head)       // 添加数据时“触顶”   
        q->full = true;  
    q->empty = false;  
  
    return;  
}  
  
void queueDel (Queue *q, int *out)  
{  
    *out = q->buf[q->head];  
    q->head++;  
    if (q->head == QUEUE_SIZE)   // 循环队列   
        q->head = 0;  
  
    if (q->head == q->tail)       // 取出数据时“触底”   
        q->empty = true;  
    q->full = false;  
  
    return;  
}  
 

(编辑:大同站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!