复杂一点的生产者消费者-pthread

基础知识思考整理
http://blog.csdn.net/aganlengzi/article/details/51416461

/*
  生产者消费者问题:
  在缓冲区不满时,一个或一组生产者(线程或进程)向缓冲区中插入数据,
  然后由一个或一组消费者(线程或进程)提取这些产品.
  下面是利用pthread实现的线程
  可配置的生产者数目
  可配置的消费者数目
  可配置的缓冲区大小
  可配置的产品数
*/

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define PRODUCER_NUM 3              //生产者数目
#define CONSUMER_NUM 2              //消费者数目
#define ITEM_NUM 5                  //最多生产商品数
#define DELAY_TIME 3                //等待时间
#define QUEUE_SIZE (ITEM_NUM + 1)   //队列长度

typedef int ElemType;

/*
  head 指向队头前一个元素
  tail 指向队尾元素
  empty: head == tail
  full: (tial + 1)%QUEUE_SIZE == head
  insert: not full --> elem[++tail] = inserted_num
  delete: not empty --> delete[++head] 
 */
typedef struct 
{
    ElemType elem[QUEUE_SIZE];
    int head, tail;
}Queue;

Queue the_queue, *p_queue;
pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t producer_cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t consumer_cond = PTHREAD_COND_INITIALIZER;

int ERROR_CODE;

/*
  func  : init the queue
  input : Queue *p_queue
  output: none
 */
void init_queue(Queue *p_queue)
{
    memset(p_queue, 0, sizeof(*p_queue));
}

/*
  func  : judge if queue full
  input : Queue* p_queue
  output: 0 not full
          1 is full
 */
int is_queue_full(Queue *p_queue)
{
    if(p_queue->head == (p_queue->tail + 1)% QUEUE_SIZE)
        return 1;
    else
        return 0;
}

/*
  func  : judge if queue empty
  input : Queue* p_queue
  output: 0 not empty
          1 is empty
 */
int is_queue_empty(Queue *p_queue)
{
    if(p_queue->head == p_queue->tail)
        return 1;
    else
        return 0;
}

/*
  func  : get total elem num
  input : Queue* p_queue
  output: num of elem
 */
int get_queue_num(Queue *p_queue)
{
    return (p_queue->tail + QUEUE_SIZE - p_queue->head)%QUEUE_SIZE;
}

/*
  func  : insert an elem into the queue
  input : Queue* p_queue, inserted_elem
  output: 0 and ERROR_CODE=-1: full and wrong
          1: sucess
 */
int insert_queue(Queue *p_queue, ElemType inserted_elem)
{
    if(is_queue_full(p_queue))
    {
        printf("The queue is full\n");
        ERROR_CODE = -1;
        return 0;
    }
    else
    {
        p_queue->tail += 1;
        p_queue->tail %= QUEUE_SIZE;
        p_queue->elem[p_queue->tail] = inserted_elem;
        return 1;
    }
}

/*
  func  : delete an elem from the queue
  input : Queue* p_queue
  output: 0 and ERROR_CODE = -1: empty and wrong  
          other: deleted elem 
 */
int delet_queue(Queue *p_queue)
{
    if(is_queue_empty(p_queue))
    {
        printf("The queue is empty\n");
        ERROR_CODE = -1;
        return 0;
    }
    else
    {
        p_queue->head += 1;
        p_queue->head %= QUEUE_SIZE;
        return p_queue->elem[p_queue->head]; 
    }
}

/*
  func  : get tail of the queue
  input : Queue* p_queue
  output: the tail of the queue
 */
int get_queue_tail(Queue *p_queue)
{
    return p_queue->tail;
}

/*
  func  : get head of the queue
  input : Queue* p_queue
  output: the head of the queue
 */
int get_queue_head(Queue *p_queue)
{
    return p_queue->head;
}

/*
  func  : the consumer thread, detached and is a dead loop
  input : void *para, the index of the all_threads array convenient for locating
  output: void *
 */
void * consumer_thread(void *para)
{
    long thread_no = (long)para;
    while(1)
    {
        pthread_mutex_lock(&queue_lock);
        while(is_queue_empty(p_queue))
        {
            pthread_cond_wait(&consumer_cond, &queue_lock);
        }
        delet_queue(p_queue);
        if(get_queue_num(p_queue) == ITEM_NUM - 1)
        {
            pthread_cond_broadcast(&producer_cond);
        }
        printf("consumer thread[%ld] deletes queue[%d]=%d\n", thread_no, p_queue->head, p_queue->elem[p_queue->head]);
        pthread_mutex_unlock(&queue_lock);
        sleep(rand()%DELAY_TIME + 1);
    }
}


/*
  func  : the producer thread, detached and is a dead loop
  input : void *para, the index of the all_threads array convenient for locating
  output: void *
*/
void * producer_thread(void *para)
{
    long thread_no = (long)para;
    int tmp;
    while(1)
    {
        pthread_mutex_lock(&queue_lock);
        while(is_queue_full(p_queue))
        {
            pthread_cond_wait(&producer_cond, &queue_lock);
        }
        tmp = get_queue_tail(p_queue);
        insert_queue(p_queue, tmp);
        if(get_queue_num(p_queue) == 1)
        {
            pthread_cond_broadcast(&consumer_cond);
        }
        printf("producer thread[%ld] produces queue[%d]=%d\n", thread_no, p_queue->tail, tmp );
        pthread_mutex_unlock(&queue_lock);
        sleep(rand()%DELAY_TIME + 1);
    }
}



int main(int argc, char const *argv[])
{
    // using pointer but not the variable
    p_queue = &the_queue;
    // storing all the ids of the threads
    pthread_t all_threads[CONSUMER_NUM + PRODUCER_NUM];
    // attributes
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    // tmp index
    int index;

    init_queue(p_queue);

    // creating the consumers
    for (index = 0; index < CONSUMER_NUM; ++index)
    {
        pthread_create(&all_threads[index], &attr, consumer_thread, (void*)index);
    }

    sleep(2);

    // creating the producers
    for (index = 0; index < PRODUCER_NUM; ++index)
    {
        pthread_create(&all_threads[index + CONSUMER_NUM], &attr, producer_thread, (void*)index);
    }

    //destroy the initialized attribute variable
    pthread_attr_destroy(&attr);

    //pthread_exit(NULL);
    while(1);
    return 0;
}

[1] http://www.cnblogs.com/clover-toeic/p/4029269.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生产者消费者问题可以使用线程和信号量来实现。 以下是一个简单的C语言程序,使用互斥锁和条件变量来解决生产者消费者问题: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int in = 0; int out = 0; pthread_mutex_t mutex; sem_t empty; sem_t full; void* producer(void* arg) { int item; while (1) { item = rand(); sem_wait(&empty); pthread_mutex_lock(&mutex); buffer[in] = item; in = (in + 1) % BUFFER_SIZE; printf("Produced item: %d\n", item); pthread_mutex_unlock(&mutex); sem_post(&full); } } void* consumer(void* arg) { int item; while (1) { sem_wait(&full); pthread_mutex_lock(&mutex); item = buffer[out]; out = (out + 1) % BUFFER_SIZE; printf("Consumed item: %d\n", item); pthread_mutex_unlock(&mutex); sem_post(&empty); } } int main() { pthread_t tid1, tid2; pthread_mutex_init(&mutex, NULL); sem_init(&empty, 0, BUFFER_SIZE); sem_init(&full, 0, 0); pthread_create(&tid1, NULL, producer, NULL); pthread_create(&tid2, NULL, consumer, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_mutex_destroy(&mutex); sem_destroy(&empty); sem_destroy(&full); return 0; } ``` 在该程序中,生产者线程和消费者线程无限循环地执行。生产者线程生成一个随机数并将其放入缓冲区中,然后唤醒消费者线程。消费者线程从缓冲区中获取一个项目并打印出来,然后唤醒生产者线程。 互斥锁用于保护缓冲区的读写操作,而信号量则用于控制缓冲区的空闲和已用空间。当缓冲区已满时,生产者线程被阻塞在 sem_wait(&empty) 处,直到有空间可用。当缓冲区为空时,消费者线程被阻塞在 sem_wait(&full) 处,直到有项目可用。 注意,该程序仅为示例,实际应用中可能需要更复杂的同步机制和错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值