Linux多线程之同步2 —— 生产者消费者模型
思路
生产者和消费者(互斥与同步)。资源用队列模拟(要上锁,一个时间只能有一个线程操作队列)。
m个生产者。拿到锁,且产品不满,才能生产。当产品满,则等待,等待消费者唤醒。当产品由空到不空,通知消费者。
n个消费者。拿到锁,且有产品,才能消费。当产品空,则等待,等待生产者唤醒。当产品由满到不满,通知生产者。
生产者条件:队列不满
消费者条件:队列不空
因此有两个条件变量。
代码
/*************************************************************************
> File Name: main.c
> Author: KrisChou
> Mail:zhoujx0219@163.com
> Created Time: Tue 26 Aug 2014 02:55:01 PM CST
************************************************************************/ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define CNT 20 /* 最多生产20个产品 */ /* 用队列模拟车间 */
/* front和tail初始化均为0,tail是下一个资源生成的下一个数组空间下标 */
typedef struct tag
{
int s_arr[CNT + 1] ; /* 生产20个产品,必须有21个空间,因为如果空间都装满产品,无法区别队列满和队列空 */
int s_front ;
int s_tail ;
}QUEUE,*pQUEUE ;
QUEUE my_que ;
/* 资源为空 */
int que_empty(pQUEUE pq)
{
return pq ->s_front == pq -> s_tail ;
}
/* 资源为满 */
int que_full(pQUEUE pq)
{
return (pq -> s_tail + 1)% (CNT+1) == pq -> s_front ;
}
int que_cnt(pQUEUE pq)
{
return (pq -> s_tail - pq ->s_front + CNT + 1)% (CNT + 1) ;
}
pthread_mutex_t mutex ;
pthread_cond_t cond_pro, cond_con ; void* pro_handler(void* arg)
{
pthread_detach(pthread_self());
while(1)
{
pthread_mutex_lock(&mutex) ;
while(que_full(&my_que))
{
pthread_cond_wait(&cond_pro, &mutex);
}
my_que.s_arr[my_que.s_tail ] = rand() % 1000 ;
my_que.s_tail = (my_que.s_tail + 1)% (CNT + 1) ;
if(que_cnt(&my_que) == 1)
{
pthread_cond_broadcast(&cond_con);
}
printf("produce a product, total num : %d \n", que_cnt(&my_que));
pthread_mutex_unlock(&mutex);
sleep(rand()%3 + 1);
}
}
void* con_handler(void* arg)
{
pthread_detach(pthread_self());
while(1)
{
pthread_mutex_lock(&mutex);
while(que_empty(&my_que))
{
pthread_cond_wait(&cond_con, &mutex);
}
my_que.s_front = (my_que.s_front + 1) % (CNT + 1) ;
if(que_cnt(&my_que) == CNT - 1)
{
/*由于我们的主线程是等消费者线程创建完之后,再创建生产者线程,
因此一开始所有消费者线程都会挂起,在条件变量cond_pro的队列里排队
因此需要用broadcast通知所有消费者线程。
不然一次就通知一个生产者线程,就此消费者线程会抢锁。
当然,如果一开始主线程先创建生产者线程,再创建消费者线程,
由于生产者线程不会全部阻塞,因此可以使用signal来唤醒一个 */
pthread_cond_broadcast(&cond_pro);
}
printf("consume a product, total num: %d \n", que_cnt(&my_que));
pthread_mutex_unlock(&mutex);
sleep(rand()%3 + 1);
} }
int main(int argc, char* argv[])//exe pro_num con_num
{
int con_cnt , pro_cnt ;
my_que.s_front = 0 ;
my_que.s_tail = 0 ;
pro_cnt = atoi(argv[1]) ;
con_cnt = atoi(argv[2]) ;
srand(getpid());
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond_pro, NULL);
pthread_cond_init(&cond_con, NULL);
pthread_t* arr = (pthread_t*)calloc(con_cnt + pro_cnt, sizeof(pthread_t));
int index = 0 ;
while(con_cnt > 0)
{
pthread_create(arr + index , NULL, con_handler, NULL);
index ++ ;
con_cnt -- ;
}
sleep(5);
while(pro_cnt > 0)
{
pthread_create(arr + index , NULL, pro_handler, NULL);
index ++ ;
pro_cnt -- ;
}
while(1) ;
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond_pro);
pthread_cond_destroy(&cond_con);
return 0 ;
}
Makefile
main:main.c
gcc -o $@ $< -lpthread
Linux多线程之同步2 —— 生产者消费者模型的更多相关文章
- Linux同步互斥(Peterson算法,生产者消费者模型)
同步 两个或两个以上随时间变化的量在变化过程中保持一定的相对关系. 互斥 对一组并发进程,一次只有一个进程能够访问一个给定的资源或执行一个给定的功能. 互斥技术可以用于解决诸如资源争用之类的冲突,还可 ...
- 进程,线程,GIL,Python多线程,生产者消费者模型都是什么鬼
1. 操作系统基本知识,进程,线程 CPU是计算机的核心,承担了所有的计算任务: 操作系统是计算机的管理者,它负责任务的调度.资源的分配和管理,统领整个计算机硬件:那么操作系统是如何进行任务调度的呢? ...
- 多道技术 进程 线程 协程 GIL锁 同步异步 高并发的解决方案 生产者消费者模型
本文基本内容 多道技术 进程 线程 协程 并发 多线程 多进程 线程池 进程池 GIL锁 互斥锁 网络IO 同步 异步等 实现高并发的几种方式 协程:单线程实现并发 一 多道技术 产生背景 所有程序串 ...
- Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会有解决很多问题]生产者消费者模型
http://blog.csdn.net/a352193394/article/details/39503857 Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会 ...
- python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型
一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...
- python开发进程:互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型
一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...
- java多线程:线程间通信——生产者消费者模型
一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是,多个线程之间如何协作呢? 我们看一个仓库 ...
- java 线程池、多线程实战(生产者消费者模型,1 vs 10) 附案例源码
导读 前二天写了一篇<Java 多线程并发编程>点我直达,放国庆,在家闲着没事,继续写剩下的东西,开干! 线程池 为什么要使用线程池 例如web服务器.数据库服务器.文件服务器或邮件服务器 ...
- Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型
Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...
随机推荐
- Go support for Android
Go support for Android David Crawshaw June 2014 Abstract We propose to introduce Go support for the ...
- 从零开始学ios开发(三):第一个有交互的app
感谢大家的关注,也给我一份动力,让我继续前进.有了自己的家庭有了孩子,过着上有老下有小的生活,能够挤出点时间学习真的很难,每天弄好孩子睡觉已经是晚上10点左右了,然后再弄自己的事情,一转眼很快就到12 ...
- MVC4.0 WebApi如何自定义返回数据类型
1.客户端可以通过HTTP Accept消息头来通知服务器客户端想要什么样的MIME类型数据,例如:application/json则代表告诉服务器想要的是Json数据 2.服务器端撇开客户端的请求类 ...
- windows CE 6.0编译报BLDDEMO: There were errors building MY283错误解决办法
今天开始正式进入windows ce程序开发. 第一次编译windows ce6.0的系统,25分钟编译后报:BLDDEMO: There were errors building MY283 错误. ...
- WCF note1
Summary of WCF Client to use service use ChannelFactory to create proxy to use service. Client code ...
- ASP运行流程(主要的类笔记)
个人笔记:参考汤姆大叔的MVC之前那些事系列整理 client端发送页面请求,被IIS的某个进程截获,它根据申请的页面后缀(.aspx)不同,调用不同的页面处理程序(.asp->asp.dll ...
- jQuery4ajax
1.jQuery对ajax编程的支持 (1)load方法: 作用:将服务器返回的数据直接添加到符合要求的dom节点之上. 用法:load(url,[data]); url:请求地址,比如"p ...
- Js作用域与作用域链详解[转]
一直对Js的作用域有点迷糊,今天偶然读到JavaScript权威指南,立马被吸引住了,写的真不错.我看的是第六版本,相当的厚,大概1000多页,Js博大精深,要熟悉精通需要大毅力大功夫. 一:函数作 ...
- pietty and putty safe password
如何让putty记住密码..pietty也一样的不能记住密码. 找不到好的的方法...只好试着按照参数格式做了一个快捷方式..F:\soft\pietty.exe -pw password123 ro ...
- Notes of the scrum meeting(11/3)
meeting time:19:30~20:00p.m.,November 3th,2013 meeting place:20号公寓楼前 attendees: 顾育豪 ...