最简单的生产者消费者-pthread

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

最基本的生产者消费者模型:
一个生产者
一个消费者
一个BUFFER
一个锁
两个条件变量
/*

pthread_cond_wait的大致操作流程:
  1. 解除已被调用线程锁住的锁
  2. 等待条件,睡眠阻塞
  3. 条件到来,醒来
  4. 返回前锁住解开的调用线程锁住的锁
pthread_cond_signal用于唤醒在某个条件变量上等待的线程,一般是1个
pthread_cond_broadcast唤醒所有在某个条件变量上等待的线程
为什么要和mutex锁绑定使用?

the purppose of lock is to prevent simultaneous(同时的) request of wait()
if cond_signal happens, it will stop blocking and lock the mutex atomatically.

signal和lock的位置

pthread_cond_signal既可以放在pthread_mutex_lock和pthread_mutex_unlock之间,
也可以放在pthread_mutex_lock和pthread_mutex_unlock之后,但是各有有缺点。

之间:
pthread_mutex_lock
xxxxxxx
pthread_cond_signal
pthread_mutex_unlock

优点:下面那种方式的缺点
缺点:在某些线程的实现中,会造成等待线程(调用wait的线程)从内核中唤醒(由于cond_signal)然后又回到内核空间(因为cond_wait返回后会有原子加锁的行为),所以一来一回会有性能的问题。
但是在Linux Threads不会有这个问题,因为在Linux 线程中,有两个队列,分别是cond_wait队列和mutex_lock队列,
cond_signal只是让线程从cond_wait队列移到mutex_lock队列,而不用返回到用户空间,不会有性能的损耗。
所以在Linux中推荐使用这种模式。

之后:
pthread_mutex_lock
xxxxxxx
pthread_mutex_unlock
pthread_cond_signal

优点:上面那种方式的缺点
缺点:如果unlock和signal之前,有个低优先级的线程(其它的)正在mutex上等待的话,
那么这个低优先级的线程就会抢占高优先级的线程(假设是wait这个cond的线程),因为资源获得而获得执行,
而wait这个cond的线程资源还没有得到,只能等待. 典型的优先级翻转.

/*
  生产者-消费者 基本模型
  一个生产者一个消费者一个buffer
  需要:
  1. 一个buffer
  2. buffer的锁
  3. 通知机制,producer写好之后通知consumer 
  4. flag 生产者和消费者之间的协议
  5. 一个生产者线程
  6. 一个消费者线程
 */

#include <pthread.h>
#include <stdio.h>

//buffer数据类型 可扩展
typedef struct
{
    int num;
}BUFFER;

#define MAX_NUM 1000

//buffer
BUFFER buf;
//lock
pthread_mutex_t pc_mutex;
//通知
pthread_cond_t pc_condp, pc_condc;


/*
  生产者
 */

void * producer(void * nul)
{
    int i;
    for (i = 1; i < MAX_NUM; ++i)
    {
        pthread_mutex_lock(&pc_mutex);

        //等待条件变量
        while(buf.num != 0)
        {
            pthread_cond_wait(&pc_condp, &pc_mutex);
        }
        //生产
        buf.num = i;
        printf("producer produces %d \n", buf.num );
        //通知
        pthread_cond_signal(&pc_condc);
        pthread_mutex_unlock(&pc_mutex);
    }
    pthread_exit(NULL);

}

/*
  消费者
 */

void * consumer(void * nul)
{
    int i;
    for (i = 1; i < MAX_NUM; ++i)
    {
        pthread_mutex_lock(&pc_mutex);

        //等待条件变量
        while(buf.num == 0) {
            pthread_cond_wait(&pc_condc, &pc_mutex);
        }
        //条件达到
        printf("consumer consumes %d \n", buf.num);
        buf.num = 0;
        //通知consumer
        pthread_cond_signal(&pc_condp);
        pthread_mutex_unlock(&pc_mutex);
    }

    pthread_exit(NULL);
}



int main(int argc, char const *argv[])
{
    pthread_t thread[2];
    pthread_attr_t attr;

    buf.num = 0;

    //锁和条件变量
    pthread_mutex_init(&pc_mutex, NULL);
    pthread_cond_init(&pc_condp, NULL);
    pthread_cond_init(&pc_condc, NULL);

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    //producer
    pthread_create(&thread[0], &attr, producer, NULL);
    //consumer
    pthread_create(&thread[1], &attr, consumer, NULL);

    //连接线程
    pthread_join(thread[0], NULL);
    pthread_join(thread[1], NULL);

    //清理资源
    pthread_mutex_destroy(&pc_mutex);
    pthread_cond_destroy(&pc_condc);
    pthread_cond_destroy(&pc_condp);
    pthread_attr_destroy(&attr);

    pthread_exit(NULL);
    return 0;
}

[1] http://blog.chinaunix.net/uid-27164517-id-3282242.html
*/

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言生产者消费者问题是一个经典的多线程同步问题,其场景模拟了生产者和消费者在共享有限缓冲区时的操作。具体来说,生产者向缓冲区生产产品,消费者从缓冲区消费产品,两者需要协调合作,保证生产和消费的平衡,避免缓冲区溢出或者消费者阻塞等问题。 解决该问题的方法有很多种,其中最常用的是使用互斥锁和条件变量。生产者和消费者共享一个互斥锁,用于保证缓冲区的互斥访问。同时,使用两个条件变量,分别表示缓冲区非空和非满。当缓冲区非空时,消费者可以从缓冲区中取出产品;当缓冲区非满时,生产者可以将产品放入缓冲区中。通过这种方式,生产者和消费者可以协调合作,避免了缓冲区溢出或者消费者阻塞等问题。 以下是一个简单的C语言生产者消费者问题的实现代码: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int in = 0, out = 0; int count = 0; pthread_mutex_t mutex; pthread_cond_t not_full; pthread_cond_t not_empty; void *producer(void *arg) { int item; while (1) { item = rand() % 1000; pthread_mutex_lock(&mutex); while (count == BUFFER_SIZE) { pthread_cond_wait(&not_full, &mutex); } buffer[in] = item; in = (in + 1) % BUFFER_SIZE; count++; printf("Producer produces %d, count = %d\n", item, count); pthread_cond_signal(&not_empty); pthread_mutex_unlock(&mutex); sleep(rand() % 3); } } void *consumer(void *arg) { int item; while (1) { pthread_mutex_lock(&mutex); while (count == 0) { pthread_cond_wait(&not_empty, &mutex); } item = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; printf("Consumer consumes %d, count = %d\n", item, count); pthread_cond_signal(&not_full); pthread_mutex_unlock(&mutex); sleep(rand() % 3); } } int main() { pthread_t tid1, tid2; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&not_full, NULL); pthread_cond_init(&not_empty, NULL); pthread_create(&tid1, NULL, producer, NULL); pthread_create(&tid2, NULL, consumer, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&not_full); pthread_cond_destroy(&not_empty); return 0; } ``` 在该代码中,我们使用了互斥锁和条件变量来协调生产者和消费者的操作。其中,互斥锁用于保证缓冲区的互斥访问,条件变量`not_full`表示缓冲区非满,条件变量`not_empty`表示缓冲区非空。在生产者和消费者的操作中,分别使用`pthread_cond_wait`和`pthread_cond_signal`来等待和唤醒条件变量,从而协调生产者和消费者的操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值