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()移 ...
随机推荐
- Convert Geometry data into a Geography data in MS SQL Server
DECLARE @geog GEOGRAPHY; DECLARE @geom GEOMETRY; ); SET @geom = @geom.MakeValid() --Force to valid g ...
- Thread系列——Thread.Sleep(0)
转载自:http://www.cnblogs.com/ATually/archive/2010/10/21/1857261.html 线程这一概念,可以理解成进程中的一个小单元.这个单元是一个独立的执 ...
- Linux C 文件与目录2 文件的打开与关闭
文件的打开与关闭 open和close 文件的打开指的是从磁盘中找到一个文件,返回一个整形的打开文件顺序的编号.打开的文件处于可读.可写状态.文件的关闭指的是释放打开的文件,是文件处于不可读写的状态. ...
- VS2013中如何更改主题颜色(深色)和恢复默认的窗口布局
1.通常情况下,我们会根据个人爱好更改VS2013的主题颜色,一开始我喜欢白色,后来我偏爱深色. 依次选择:工具->选项->常规->主题->深色->确定,ok 2.我们在 ...
- android数独游戏
最近没事干,照着视频教程写了一个数独游戏,很粗糙还有很多要修改的地方.下面就来说说这个游戏吧 1.自定义一个View控件,用来在屏幕上显示一个9*9的格子,其实就是横着画8条线,竖着画8跳线,然后将其 ...
- ubuntu重置root密码
from: http://mmicky.blog.163.com/blog/static/150290154201398113034698/ 使用ubuntu的时候忘记了root密码该如何重置?我使用 ...
- Codeforces Round #254 (Div. 1) C. DZY Loves Colors 线段树
题目链接: http://codeforces.com/problemset/problem/444/C J. DZY Loves Colors time limit per test:2 secon ...
- 关于Web服务器域名设置相关知识积累
1.第一个问题,如何将一个服务器映射到一个域名上呢? 在申请域名的时候,会配置服务器IP和域名的对应关系,所以如果系统中只有一个应用的情况下,应用服务器不需要做任何配置. 2.在Tomcat服务 ...
- 【CentOS】搭建git服务器
参考资料: https://github.com/jackliu2013/recipes/blob/master/doc/linux/CentOS_6.4_git服务器搭建.md http://blo ...
- Netty 对通讯协议结构设计的启发和总结
Netty 通讯协议结构设计的总结 key words: 通信,协议,结构设计,netty,解码器,LengthFieldBasedFrameDecoder 原创 包含与机器/设备的通讯协议结构的设计 ...