基于POSIX信号量实现生产者消费模型
2016-04-24 20:44
483 查看
一.基础知识
1.1 system V版本的信号量和POSIX下信号量的区别
我们前面讲过进程间通信有三种形式:管道、消息队列、信号量。这个信号量是system V版本下,以信号量集形式申请存在的,它标识着一个临界资源的有无从而控制不同的进程能否访问到该临界资源。但,现在,我们要讲的信号量是基于POSIX下的信号量,它用来标识资源的个数。
1.2 互斥锁和信号量
上篇所述,互斥锁(Mutex)可看作是某种资源的可用数,Mutex变量是非0即1的,初始化时Mutex为1,表示有一个可用资源;加锁时获得该资源,将Mutex减到0,表示不再有可用资源;解锁时释放该资源,将Mutex重新加到1,表示又有了一个可用资源。 即,信号量和Mutex作用类似,表示可用资源的数量,和Mutex不同的是信号量的数量可以大于1。如果信号量描述的资源数目是1时,此时的信号量就和互斥锁相同!
这种信号量不仅可用于同一进程的线程间同步,也可用于不同进程间的同步。
二.相关函数
2.1初始化
![](http://s1.51cto.com/wyfs02/M02/7F/60/wKioL1cclRfwj8OhAAAeIbLxH5E257.png)
semaphore变量的类型为sem_t,sem_init()初始化一个semaphore变量,
pshared:参数为0表示信号量用于同一进程的线程间同步
value:可用资源的数量
2.2 释放资源
![](http://s4.51cto.com/wyfs02/M02/7F/60/wKioL1cco_yBeoz2AAAZ6bdz1gU503.png)
2.3 P、V操作
![](http://s3.51cto.com/wyfs02/M01/7F/63/wKiom1ccok_A1kosAAAoFPKITfc371.png)
sem_wait():获得资源(P操作-1),使semaphore的值减1,如果调用sem_wait()时semaphore的值已经是0,则挂起等待。如果不希望挂起等待,可以调用sem_trywait() 。
sem_post():释放资源(V操作+1),使semaphore 的值加1,同时唤醒挂起等待的线程。
三. 相关代码(多生产者多消费者模型)
![](http://s3.51cto.com/wyfs02/M02/7F/61/wKioL1ccuwPRWU6xAABCPRQ6p2E452.png)
四.分析与总结
1)单生产但消费者模型,因为P、V操作已经让两者有序,相当于完成了同步与互斥(上述代码实现中去掉加锁解锁即第20,25,35,40行);多生产者多消费者模型,即上述代码实现。(因为消费者和消费者之间存在互斥问题,生产者和生产者之间也存在互斥问题)
2)加锁解锁的方式还有一种,即加在sem_wait之前,但这样可能会造成死锁问题:若消费者先进入,申请data,而此时产生data的生产者被挂起等待。
1.1 system V版本的信号量和POSIX下信号量的区别
我们前面讲过进程间通信有三种形式:管道、消息队列、信号量。这个信号量是system V版本下,以信号量集形式申请存在的,它标识着一个临界资源的有无从而控制不同的进程能否访问到该临界资源。但,现在,我们要讲的信号量是基于POSIX下的信号量,它用来标识资源的个数。
1.2 互斥锁和信号量
上篇所述,互斥锁(Mutex)可看作是某种资源的可用数,Mutex变量是非0即1的,初始化时Mutex为1,表示有一个可用资源;加锁时获得该资源,将Mutex减到0,表示不再有可用资源;解锁时释放该资源,将Mutex重新加到1,表示又有了一个可用资源。 即,信号量和Mutex作用类似,表示可用资源的数量,和Mutex不同的是信号量的数量可以大于1。如果信号量描述的资源数目是1时,此时的信号量就和互斥锁相同!
这种信号量不仅可用于同一进程的线程间同步,也可用于不同进程间的同步。
二.相关函数
2.1初始化
![](http://s1.51cto.com/wyfs02/M02/7F/60/wKioL1cclRfwj8OhAAAeIbLxH5E257.png)
semaphore变量的类型为sem_t,sem_init()初始化一个semaphore变量,
pshared:参数为0表示信号量用于同一进程的线程间同步
value:可用资源的数量
2.2 释放资源
![](http://s4.51cto.com/wyfs02/M02/7F/60/wKioL1cco_yBeoz2AAAZ6bdz1gU503.png)
2.3 P、V操作
![](http://s3.51cto.com/wyfs02/M01/7F/63/wKiom1ccok_A1kosAAAoFPKITfc371.png)
sem_wait():获得资源(P操作-1),使semaphore的值减1,如果调用sem_wait()时semaphore的值已经是0,则挂起等待。如果不希望挂起等待,可以调用sem_trywait() 。
sem_post():释放资源(V操作+1),使semaphore 的值加1,同时唤醒挂起等待的线程。
三. 相关代码(多生产者多消费者模型)
//test.c 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<pthread.h> 4 #include<semaphore.h> 5 6 #define MAX 20 7 static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER; 8 sem_t blank; 9 sem_t data; 10 11 int buf[MAX]; 12 13 void* product(void* arg) 14 { 15 int i=0; 16 int index=0; 17 while(1) 18 { 19 sem_wait(&blank); 20 pthread_mutex_lock(&lock); 21 buf[index++]=i++; 22 index%=MAX; 23 printf("product%d done...val is :%d\n",(int)arg,i-1); 24 sem_post(&data); 25 pthread_mutex_unlock(&lock); 26 sleep(2); 27 } 28 } 29 void* consumer(void* arg) 30 { 31 int index=0; 32 while(1) 33 { 34 sem_wait(&data); 35 pthread_mutex_lock(&lock); 36 int val=buf[index++]; 37 index%=MAX; 38 printf("consumer%d done...val is:%d\n",(int)arg,val); 39 sem_post(&blank); 40 pthread_mutex_unlock(&lock); 41 sleep(1); 42 } 43 } 44 int main() 45 { 46 sem_init(&blank,0,MAX); 47 sem_init(&data,0,0); 48 49 pthread_t product1; 50 pthread_t product2; 51 pthread_t product3; 52 pthread_t consumer1; 53 pthread_t consumer2; 54 pthread_t consumer3; 55 56 pthread_create(&product1,NULL,product,(void*)1); 57 pthread_create(&product2,NULL,product,(void*)2); 58 pthread_create(&product3,NULL,product,(void*)3); 59 pthread_create(&consumer1,NULL,consumer,(void*)1); 60 pthread_create(&consumer2,NULL,consumer,(void*)2); 61 pthread_create(&consumer3,NULL,consumer,(void*)3); 62 63 pthread_join(product1,NULL); 64 pthread_join(product2,NULL); 65 pthread_join(product3,NULL); 66 pthread_join(consumer1,NULL); 67 pthread_join(consumer2,NULL); 68 pthread_join(consumer3,NULL); 69 70 sem_destroy(&blank); 71 sem_destroy(&data); 72 73 pthread_mutex_destroy(&lock); 74 75 return 0; 76 } //makefile 1 test:test.c 2 gcc -o $@ $^ -lpthread 3 .PHONY:clean 4 clean: 5 rm -f test输出结果:
![](http://s3.51cto.com/wyfs02/M02/7F/61/wKioL1ccuwPRWU6xAABCPRQ6p2E452.png)
四.分析与总结
1)单生产但消费者模型,因为P、V操作已经让两者有序,相当于完成了同步与互斥(上述代码实现中去掉加锁解锁即第20,25,35,40行);多生产者多消费者模型,即上述代码实现。(因为消费者和消费者之间存在互斥问题,生产者和生产者之间也存在互斥问题)
2)加锁解锁的方式还有一种,即加在sem_wait之前,但这样可能会造成死锁问题:若消费者先进入,申请data,而此时产生data的生产者被挂起等待。
相关文章推荐
- PowerShell实现参数互斥示例
- Lua编程示例(八):生产者-消费者问题
- 深入多线程之:深入生产者、消费者队列分析
- Ruby实现生产者和消费者代码分享
- linux多线程编程详解教程(线程通过信号量实现通信代码)
- PHP信号量基本用法实例详解
- JAVA 多线程之信号量(Semaphore)实例详解
- java解决单缓冲生产者消费者问题示例
- Linux设备驱动并发控制详解(自旋锁,信号量)
- 信号量
- 信号量、互斥锁,读写锁和条件变量的区别
- android SDK 源码 -----建造这模式(生成器模式)
- 互斥锁与条件变量的配合!
- 信号量 互斥锁 条件变量的区别
- 关于哲学家就餐问题 源代码(linux)
- 多个生产者与多个消费者的问题
- 【跟随万一老师的足迹】引用即可解决互斥问题的单元
- 【跟随万一老师的足迹】引用即可解决互斥问题的单元
- Posix信号量
- 使用信号量和关键区来实现生产者消费者