最简单的生产者消费者-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

*/

时间: 2024-10-12 21:01:52

最简单的生产者消费者-pthread的相关文章

4.利用python生成器实现简单的“生产者消费者”模型

假如说,没有生成器这种对象,那么如何实现这种简单的"生产者消费者"模型呢? import time def producer(): pro_list = [] for i in range(10000): print "包子%s制作ing" %(i) time.sleep(0.5) pro_list.append("包子%s" %i) return pro_list def consumer(pro_list): for index,stuffe

使用队列queue实现一个简单的生产者消费者模型

一.生产者消费者模型 我们去超市商店等地购买商品时,我们大部分人都会说自己是消费者,而超市的各大供货商.工厂等,自然而然地也就成了我们的生产者.如此一来,生产者有了,消费者也有了,那么将二者联系起来的超市又该作何理解呢?诚然,它本身是作为一座交易场所而诞生. 上述情形类比到实际的软件开发过程中,经常会发现:某个线程或模块的代码负责生产数据(工厂),而生产出来的数据却不得不交给另一模块(消费者)来对其进行处理,在这之间使用了队列.栈等类似超市的东西来存储数据(超市),这就抽象除了我们的生产者/消费

java多线程基本概述(六)——简单生产者消费者模式

在线程里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这个问题于是引入了生产者和消费者模式.下面实现一个简单的生产者消费者模式: 1.一个消费者一个生产者循环消费生产 package soarhu; import java.util.ArrayList; import java.util.Lis

java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

 *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时候才能消费,仓空则等待. *3.当消费者发现仓储没有产品可消费的时候,会唤醒等待生产者生产. *4.生产者在生产出可以消费的产品的时候,应该通知等待的消费者去消费. 下面先介绍个简单的生产者消费者例子:本例只适用于两个线程,一个线程生产,一个线程负责消费. 生产一个资源,就得消费一个资源. 代码如下: pub

python2.0_s12_day9之day8遗留知识(queue队列&amp;生产者消费者模型)

4.线程 1.语法 2.join 3.线程锁之Lock\Rlock\信号量 4.将线程变为守护进程 5.Event事件 * 6.queue队列 * 7.生产者消费者模型 4.6 queue队列 queue非常有用,当信息必须安全的在多个线程之间进行数据交换的时候就应该想到queue 所以,queue它能保证数据被安全的在多个线程之间进行交换,那他就是天生的线程安全. queue有那么几种: class queue.Queue(maxsize=0) # 先入先出 class queue.LifoQ

多线程的并发执行应用(生产者消费者模式)

在实际的开发中我们为了提高CPU的利用率,也提高程序的执行效率,我们经常使用多线程进行对数据进行并发处理,下面我举一个多线程并发执行的实例,大致意思就是 一个简单的生产者消费者模式,二个线程进行存数据,一个线程进行取数据. import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class BlockingQueueTest { /** * @param a

生产者/消费者模式(一)

生产者消费者问题是一个多线程同步问题的经典案例,大多数多线程编程问题都是以生产者-消费者模式为基础,扩展衍生来的.在生产者消费者模式中,缓冲区起到了连接两个模块的作用:生产者把数据放入缓冲区,而消费者从缓冲区取出数据,如下图所示: 可以看出Buffer缓冲区作为一个中介,将生产者和消费者分开,使得两部分相对独立,生产者消费者不需要知道对方的实现逻辑,对其中一个的修改,不会影响另一个,从设计模式的角度看,降低了耦合度.而对于图中处在多线程环境中Buffer,需要共享给多个多个生产者和消费者,为了保

Java数据结构之队列的实现以及队列的应用之----简单生产者消费者应用

Java数据结构之---Queue队列 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作. 队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头.队列的插入操作通常称作入队列,队列的删除操作通常称作出队列.最简单的例子就是我们平时的排队,先进先出. 顺序队列的存储结构 下图是一个有6个存储空间的顺序队列的动态示意图,图中front

Java线程学习整理--4---一个简单的生产者、消费者模型

 1.简单的小例子: 下面这个例子主要观察的是: 一个对象的wait()和notify()使用情况! 当一个对象调用了wait(),那么当前掌握该对象锁标记的线程,就会让出CPU的使用权,转而进入该对象的等待池中等待唤醒,这里说明一下,每一个对象都有一个独立的等待池和锁池! 等待池:上述的wait()后的线程会进入等待池中,处于下图线程声明周期(简单示意图) 中的这个状态,等待池中的线程任然具有对象的锁标记,但是处于休眠状态,不是可运行状态! 当该对象调用notify方法之后,就会在等待池中系统