三种关系:互斥,同步,互斥和同步
两类角色:生产者,消费者(线程)
一个交易场所:生产者消费者共享的区域

卖苹果的模型

  • dish上面只有一个苹果
  • 买家必须要等卖家把苹果放到dish上才可以去买苹果。
  • 卖家必须等待买家把苹果买走才可以生产苹果
  • pthread_mutex_lock(&mutex); 和pthread_mutex_unlock(&mutex); 成对出现,里面的操作为一个原子操作
  • pthread_cond_wait(&empty,&mutex);内部有一个加锁解锁操作
  • 过程详解
    • 苹果为0
    • 初始化时苹果为0,买家在pthread_cond_wait(&empty,&mutex); 开始等待,卖家不进入while循环,生产苹果后发出pthread_cond_signal(&empty);让正在因dish上苹果为0的买家停止等待pthread_cond_wait(&empty,&mutex);
    • 苹果为1
    • 当一个卖家进入pthread_mutex_lock(&mutex); 但是发现苹果为1时,就在while循环处等待pthread_cond_wait(&empty,&mutex);,直到买家发出信号 pthread_cond_signal(&full);卖家停止等待,此时苹果为0,跳出while循环,开始生产苹果。生产苹果后发出pthread_cond_signal(&empty);让正在因dish上苹果为0的买家停止等待pthread_cond_wait(&empty,&mutex); 这样这个过程就结束了
      *
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>int dish = 0;
pthread_cond_t full;
pthread_cond_t empty;
pthread_mutex_t mutex;void * consumer(void * arg)
{int id = (int)arg;while(1){pthread_mutex_lock(&mutex);//上锁while(dish == 0){//买家发现没有苹果开始等待pthread_cond_wait(&empty,&mutex);}usleep(100000);dish = 0;printf("consumer %d get an apple!!\n", id);//给卖家发送信号pthread_cond_signal(&full);pthread_mutex_unlock(&mutex);//解锁}return NULL;
}void * product(void *arg)
{int id = (int)arg;while(1){pthread_mutex_lock(&mutex);    while(dish == 1){pthread_cond_wait(&full,&mutex);}dish =1;printf("producer %d put an apple!!\n", id);      pthread_cond_signal(&empty);pthread_mutex_unlock(&mutex);}return NULL;
}int main()
{pthread_t tid;int set ;//初始化pthread_cond_init(&full,NULL);pthread_cond_init(&empty,NULL);pthread_mutex_init(&mutex,NULL);//四个卖家生产苹果for(int i = 0;i<4;i++){pthread_create(&tid,NULL,product,(void *)i);}//四个买家买苹果for(int i = 0;i<4;i++){pthread_create(&tid,NULL,consumer,(void *)i);}//等待thread标识的线程终止,防止僵尸进程产生pthread_join(tid,NULL);//销毁所有资源pthread_cond_destroy(&full);pthread_cond_destroy(&empty);pthread_mutex_destroy(&mutex);
}

如果对于互斥量含义尚不清楚,建议阅读Linux/UNIX系统编程手册

pthread_mutex_t
pthread_mutex_init
pthread_mutex_lock
pthread_mutex_unlock
pthread_mutex_destroy

模型采取Linux/UNIX系统编程手册
这个模型很好,也把概念讲清楚了,加了中文注释

生产者

s = pthread_mutex_lock(&mtx);
if (s != 0)errExitEN(s, "pthread_mutex_lock");avail++;        /*这是一个原子操作 */s = pthread_mutex_unlock(&mtx);
if (s != 0)errExitEN(s, "pthread_mutex_unlock");s = pthread_cond_signal(&cond);         /* 唤醒消费者 */
if (s != 0)errExitEN(s, "pthread_cond_signal");

消费者

s = pthread_mutex_lock(&mtx);
if (s != 0)errExitEN(s, "pthread_mutex_lock");while (avail == 0){           s = pthread_cond_wait(&cond, &mtx);if (s != 0)errExitEN(s, "pthread_cond_wait");
}

完整代码

#include <time.h>
#include <pthread.h>
#include "tlpi_hdr.h"static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;static int avail = 0;static void *
threadFunc(void *arg)
{int cnt = atoi((char *) arg);int s, j;for (j = 0; j < cnt; j++) {sleep(1);/* Code to produce a unit omitted */s = pthread_mutex_lock(&mtx);if (s != 0)errExitEN(s, "pthread_mutex_lock");avail++;        /* Let consumer know another unit is available */s = pthread_mutex_unlock(&mtx);if (s != 0)errExitEN(s, "pthread_mutex_unlock");s = pthread_cond_signal(&cond);         /* Wake sleeping consumer */if (s != 0)errExitEN(s, "pthread_cond_signal");}return NULL;
}int
main(int argc, char *argv[])
{pthread_t tid;int s, j;int totRequired;            /* Total number of units that all threadswill produce */int numConsumed;            /* Total units so far consumed */Boolean done;time_t t;t = time(NULL);/* Create all threads */totRequired = 0;for (j = 1; j < argc; j++) {totRequired += atoi(argv[j]);s = pthread_create(&tid, NULL, threadFunc, argv[j]);if (s != 0)errExitEN(s, "pthread_create");}/* Loop to consume available units */numConsumed = 0;done = FALSE;for (;;) {s = pthread_mutex_lock(&mtx);if (s != 0)errExitEN(s, "pthread_mutex_lock");while (avail == 0) {            /* Wait for something to consume */s = pthread_cond_wait(&cond, &mtx);if (s != 0)errExitEN(s, "pthread_cond_wait");}/* At this point, 'mtx' is locked... */while (avail > 0) {             /* Consume all available units *//* Do something with produced unit */numConsumed ++;avail--;printf("T=%ld: numConsumed=%d\n", (long) (time(NULL) - t),numConsumed);done = numConsumed >= totRequired;}s = pthread_mutex_unlock(&mtx);if (s != 0)errExitEN(s, "pthread_mutex_unlock");if (done)break;/* Perhaps do other work here that does not require mutex lock */}exit(EXIT_SUCCESS);
}

生产者消费者模型(条件变量)相关推荐

  1. Golang并发——并发技术Goroutine和channel的使用、定时器、生产者消费者、条件变量、select

    Goroutine: goroutine是Go并行设计的核心.goroutine说到底其实就是协程,它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些gor ...

  2. Python并行编程(四):多线程同步之condition(条件变量)实现带有缓冲区的生产者-消费者模型...

    什么是Condtion? 所谓condition条件变量,即这种机制是在满足了特定的条件后,线程才可以访问相关的数据. 这种同步机制就是一个线程等待特定的条件,另一个线程通知它条件已经发生.一旦条件发 ...

  3. 2022-2-3 牛客C++项目 —— 生产者消费者模型(条件变量、信号量)

    如果生产者将容器填满,需要通知消费者, 如果消费者将容器清空,需要通知生产者. (我个人觉得如果有多个生产者和消费者,就排成队列,通知第一个就行.不知道实际情况是什么样子的) /* 生产者消费者模型( ...

  4. 用条件变量实现生产者-消费者模型

    首先介绍一下条件变量 下面用条件变量来实现生产者-消费者模型 大体思路如下:生产者为链表"生产"结点,消费者"消费"结点,如果链表中没有结点,则阻塞消费者线程 ...

  5. Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型...

    一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...

  6. 生产者-消费者模型的两种实现方式

    https://www.cnblogs.com/caolicangzhu/p/7086176.html 本文主要来总结生产者-消费者模型的代码实现,至于其原理,请大家自行百度. 一.基于链表的生产-消 ...

  7. C++11 并发指南九(综合运用: C++11 多线程下生产者消费者模型详解)

    前面八章介绍了 C++11 并发编程的基础(抱歉哈,第五章-第八章还在草稿中),本文将综合运用 C++11 中的新的基础设施(主要是多线程.锁.条件变量)来阐述一个经典问题--生产者消费者模型,并给出 ...

  8. 生产者消费者模型、信号量、线程池以及单例模式的实现

    生产者消费者模型!!---对典型的应用场景设计的解决方案 生产者与消费者模型应用场景:有线程不断的生产数据,有线程不断的处理数据. 数据的生产与数据的处理:放在同一个线程中完成,因为执行流只有一个,那 ...

  9. 线程同步之 生产者消费者模型详解

    前言 博主本来没打算讲这个比较前面的知识的(博主socket编程还有两个部分没讲,进程也才写完回收僵尸进程的三种方法,信号捕捉器也才完结),但是今天有朋友来问博主,什么是生产者消费者模型,所以博主就先 ...

  10. 【Java】生产者消费者模型

    [Java]生产者消费者模型 0x1 前言 生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加产品,消费者从存储空间中取走产品,当存储空间 ...

最新文章

  1. NOJ---1408----map的运用
  2. Golang判断元素是否存在数组中
  3. Android之View基础总结(View的事件体系一)
  4. Android使用MPAndroidChat
  5. Purification(CF-330C)
  6. docker 使用技巧
  7. 要人帮忙,电脑怎么不寄过来?
  8. MATLAB如何生成scr文件,基于matlab生成的scr文件,实现autocad曲线绘制,代码问题...
  9. [python]SM4算法实现
  10. ffmpeg java 使用教程_Java使用ffmpeg
  11. 高德地图自定义点标记大小_高德地图 自定义点标记 图标大小
  12. 向量的平面投影 ProjectOnPlane
  13. matlab铁路平板车装货问题,用数学建模解决两辆铁路平板车的装货问题
  14. 每周推荐短视频:为什么理论正确但得不到预期结果?
  15. 电力电子技术实验-单相桥式全控整流电路实验
  16. 自适应网页设计的学习笔记
  17. iterm2(zsh)粘贴慢解决办法
  18. 简简单单学会写makefile
  19. Unity 3D 地形系统概述|| Unity 3D 创建地形
  20. 自动取款机如何使用无卡取款_工商银行atm怎么无卡取款?工商银行atm无卡取款操作说明...

热门文章

  1. 课时39.细线表格(理解)
  2. jq绑定的事件不生效
  3. [ZJJOI2013]K大数查询 整体二分
  4. 关于background-*的一些属性
  5. .NetCore模拟Postman的BasicAuth生成Authrization
  6. JavaScript总结(3)
  7. Python 06-字典
  8. jquery jgrid filterToolBar beforeSearch 修改postData
  9. Oracle SQL精妙SQL语句讲解(二)
  10. 利用jenkins的api来完成相关工作流程的自动化