思路

生产者和消费者(互斥与同步)。资源用队列模拟(要上锁,一个时间只能有一个线程操作队列)。

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 —— 生产者消费者模型的更多相关文章

  1. Linux同步互斥(Peterson算法,生产者消费者模型)

    同步 两个或两个以上随时间变化的量在变化过程中保持一定的相对关系. 互斥 对一组并发进程,一次只有一个进程能够访问一个给定的资源或执行一个给定的功能. 互斥技术可以用于解决诸如资源争用之类的冲突,还可 ...

  2. 进程,线程,GIL,Python多线程,生产者消费者模型都是什么鬼

    1. 操作系统基本知识,进程,线程 CPU是计算机的核心,承担了所有的计算任务: 操作系统是计算机的管理者,它负责任务的调度.资源的分配和管理,统领整个计算机硬件:那么操作系统是如何进行任务调度的呢? ...

  3. 多道技术 进程 线程 协程 GIL锁 同步异步 高并发的解决方案 生产者消费者模型

    本文基本内容 多道技术 进程 线程 协程 并发 多线程 多进程 线程池 进程池 GIL锁 互斥锁 网络IO 同步 异步等 实现高并发的几种方式 协程:单线程实现并发 一 多道技术 产生背景 所有程序串 ...

  4. Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会有解决很多问题]生产者消费者模型

    http://blog.csdn.net/a352193394/article/details/39503857  Java多线程之~~~使用Exchanger在线程之间交换数据[这个结合多线程并行会 ...

  5. python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

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

  6. python开发进程:互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

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

  7. java多线程:线程间通信——生产者消费者模型

    一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是,多个线程之间如何协作呢? 我们看一个仓库 ...

  8. java 线程池、多线程实战(生产者消费者模型,1 vs 10) 附案例源码

    导读 前二天写了一篇<Java 多线程并发编程>点我直达,放国庆,在家闲着没事,继续写剩下的东西,开干! 线程池 为什么要使用线程池 例如web服务器.数据库服务器.文件服务器或邮件服务器 ...

  9. Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型

    Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...

随机推荐

  1. Go support for Android

    Go support for Android David Crawshaw June 2014 Abstract We propose to introduce Go support for the ...

  2. 从零开始学ios开发(三):第一个有交互的app

    感谢大家的关注,也给我一份动力,让我继续前进.有了自己的家庭有了孩子,过着上有老下有小的生活,能够挤出点时间学习真的很难,每天弄好孩子睡觉已经是晚上10点左右了,然后再弄自己的事情,一转眼很快就到12 ...

  3. MVC4.0 WebApi如何自定义返回数据类型

    1.客户端可以通过HTTP Accept消息头来通知服务器客户端想要什么样的MIME类型数据,例如:application/json则代表告诉服务器想要的是Json数据 2.服务器端撇开客户端的请求类 ...

  4. windows CE 6.0编译报BLDDEMO: There were errors building MY283错误解决办法

    今天开始正式进入windows ce程序开发. 第一次编译windows ce6.0的系统,25分钟编译后报:BLDDEMO: There were errors building MY283 错误. ...

  5. WCF note1

    Summary of WCF Client to use service use ChannelFactory to create proxy to use service. Client code ...

  6. ASP运行流程(主要的类笔记)

    个人笔记:参考汤姆大叔的MVC之前那些事系列整理  client端发送页面请求,被IIS的某个进程截获,它根据申请的页面后缀(.aspx)不同,调用不同的页面处理程序(.asp->asp.dll ...

  7. jQuery4ajax

    1.jQuery对ajax编程的支持 (1)load方法: 作用:将服务器返回的数据直接添加到符合要求的dom节点之上. 用法:load(url,[data]); url:请求地址,比如"p ...

  8. Js作用域与作用域链详解[转]

     一直对Js的作用域有点迷糊,今天偶然读到JavaScript权威指南,立马被吸引住了,写的真不错.我看的是第六版本,相当的厚,大概1000多页,Js博大精深,要熟悉精通需要大毅力大功夫. 一:函数作 ...

  9. pietty and putty safe password

    如何让putty记住密码..pietty也一样的不能记住密码. 找不到好的的方法...只好试着按照参数格式做了一个快捷方式..F:\soft\pietty.exe -pw password123 ro ...

  10. Notes of the scrum meeting(11/3)

    meeting time:19:30~20:00p.m.,November 3th,2013 meeting place:20号公寓楼前 attendees: 顾育豪                  ...