linux中的生产者和消费者问题--信号量 互斥 同步
2013-11-05 16:23
253 查看
互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源,如“第一类读写者模型”。
生产者-消费者模型
生产者-消费者模型是指:
1. 生产者进行生产将物品放入仓库,同一时间只能有一个生产者将物品放入仓库,如果仓库满,生产者等待。
2. 消费者从仓库中取出物品,同一时间只能有一个消费者取出物品,如果仓库空,消费者等待;
3. 生产者将物品放入仓库时消费者不能同时取;
4. 消费者取物品时生产者不能放入物品;
总之,就是生产者群体或消费者群体内部是互斥的,两个群体之间是同步的。
当只有一个生产者、消费者时,由于同一群体内部不需要互斥,所以只需在群体之间实 现同步即可。
这个程序容易出错误的就是设置同步信号量和互斥信号量的顺序出错, 如在生产者或者消费者方法中把互斥信号量放在同步信号量的外层. 这样在内层中某个sem_wait不一定能通过, 从而造成死锁现象.
在多个消费者和一个消费者的不同就是是否需要互斥锁。
同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源,如“第一类读写者模型”。
生产者-消费者模型
生产者-消费者模型是指:
1. 生产者进行生产将物品放入仓库,同一时间只能有一个生产者将物品放入仓库,如果仓库满,生产者等待。
2. 消费者从仓库中取出物品,同一时间只能有一个消费者取出物品,如果仓库空,消费者等待;
3. 生产者将物品放入仓库时消费者不能同时取;
4. 消费者取物品时生产者不能放入物品;
总之,就是生产者群体或消费者群体内部是互斥的,两个群体之间是同步的。
当只有一个生产者、消费者时,由于同一群体内部不需要互斥,所以只需在群体之间实 现同步即可。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <semaphore.h> #define N 2 // 消费者或者生产者的数目 #define M 10 // 缓冲数目 int in = 0; // 生产者放置产品的位置 int out = 0; // 消费者取产品的位置 int buff[M] = {0}; // 缓冲初始化为0, 开始时没有产品 sem_t empty_sem; // 同步信号量, 当满了时阻止生产者放产品 sem_t full_sem; // 同步信号量, 当没产品时阻止消费者消费 pthread_mutex_t mutex; // 互斥信号量, 一次只有一个线程访问缓冲 int product_id = 0; //生产者id int prochase_id = 0; //消费者id /* 打印缓冲情况 */ void print() { int i; for(i = 0; i < M; i++) printf("%d ", buff[i]); printf("/n"); } /* 生产者方法 */ void *product() { int id = ++product_id; while(1) { // 用sleep的数量可以调节生产和消费的速度,便于观察 sleep(1); //sleep(1); sem_wait(&empty_sem); pthread_mutex_lock(&mutex); in = in % M; printf("product%d in %d. like: /t", id, in); buff[in] = 1; print(); ++in; pthread_mutex_unlock(&mutex); sem_post(&full_sem); } } /* 消费者方法 */ void *prochase() { int id = ++prochase_id; while(1) { // 用sleep的数量可以调节生产和消费的速度,便于观察 sleep(1); //sleep(1); sem_wait(&full_sem); pthread_mutex_lock(&mutex); out = out % M; printf("prochase%d in %d. like: /t", id, out); buff[out] = 0; print(); ++out; pthread_mutex_unlock(&mutex); sem_post(&empty_sem); } } int main() { pthread_t id1 ; pthread_t id2 ; int i; int ret ; // 初始化同步信号量 int ini1 = sem_init(&empty_sem, 0, M); int ini2 = sem_init(&full_sem, 0, 0); if(ini1 && ini2 != 0) { printf("sem init failed /n"); exit(1); } //初始化互斥信号量 int ini3 = pthread_mutex_init(&mutex, NULL); if(ini3 != 0) { printf("mutex init failed /n"); exit(1); } // 创建N个生产者线程 for(i = 0; i < N; i++) { ret[i] = pthread_create(&id1[i], NULL, product, (void *)(&i)); if(ret[i] != 0) { printf("product%d creation failed /n", i); exit(1); } } //创建N个消费者线程 for(i = 0; i < N; i++) { ret[i] = pthread_create(&id2[i], NULL, prochase, NULL); if(ret[i] != 0) { printf("prochase%d creation failed /n", i); exit(1); } } //销毁线程 for(i = 0; i < N; i++) { pthread_join(id1[i],NULL); pthread_join(id2[i],NULL); } exit(0); }
这个程序容易出错误的就是设置同步信号量和互斥信号量的顺序出错, 如在生产者或者消费者方法中把互斥信号量放在同步信号量的外层. 这样在内层中某个sem_wait不一定能通过, 从而造成死锁现象.
在多个消费者和一个消费者的不同就是是否需要互斥锁。
相关文章推荐
- 生产者-消费者问题实现 (linux下C同步信号量和互斥信号量的应用)
- Linux下信号量实现进程同步、互斥(生产者消费者问题)
- linux网络编程之posix 线程(三):posix 匿名信号量与互斥锁 示例生产者--消费者问题
- Linux下生产者消费者问题详细分析(操作系统期中考试论文---并发程序的同步和互斥)
- 进程同步---生产者与消费者问题以及进程同步机制--信号量及P、V操作
- 并发与同步、信号量与管程、生产者消费者问题
- 三个同步与互斥问题之生产者与消费者
- 进程同步---生产者与消费者问题以及进程同步机制--信号量及P、V操作
- 【线程】多线程同步互斥-条件变量与信号量,生产者与消费者问题
- 进程、线程知识点总结和同步(消费者生产者,读者写者三类问题)、互斥、异步、并发、并行、死锁、活锁的总结
- 进程同步---生产者与消费者问题以及进程同步机制--信号量及P、V操作
- Linux下进程的同步互斥实例——生产者消费者
- 经典同步问题linux下的C实现:生产者-消费者问题,读者-写者问题,哲学家问题
- 进程同步---生产者与消费者问题以及进程同步机制--信号量及P、V操作
- Linux互斥与同步应用(三):posix线程实现单个生产者和单个消费者模型
- 进程间同步互斥经典问题(一)生产者-消费者问题
- 进程同步---生产者与消费者问题以及进程同步机制--信号量及P、V操作
- Linux下进程的同步互斥实例——生产者消费者
- 进程间同步互斥经典问题(一)生产者-消费者问题
- 进程同步---生产者与消费者问题以及进程同步机制--信号量及P、V操作