生产者与消费者模型(二)
2017-07-03 01:19
267 查看
在上一篇博客中我们了解了什么是生产者与消费者模型?
也掌握了生产者与消费者模型的规则,并且实现了基于单链表的生产者与消费者模型,但是我们实现的基于单链表的生产者与消费者模型还是存在问题,存在死锁的问题,如果想深入理解死锁问题的,可以去看下我总结的死锁的博客。
这篇博客我们主要来实现基于环形队列的生产者与消费者模型。
由于上一篇博客已经讲清楚了关于生产者与消费者的各种问题,所以这篇博客我们就直接来实现。
(如果消费者可以超过生产者的话,那么消费者可能会读取到垃圾数据)。
2.生产者永远不能将消费者包围一圈
(如果生产者的优先级很高,消费者的优先级很低,如果生产者可以将消费者包围一圈,那么生产者可能就会覆盖掉原来的旧数据(消费者还没来得及消费的数据))。
由上面的两条规则可知:
1.当生产者将环形队列写满时,这时生产者会被挂起等待。(等待数据被消费者读取走)。
2.当消费者将环形队列中的数据读取完时,这时消费者就会被挂起等待。(等待写入生产者写入的新的数据)。
结果如下:
返回值:
成功返回0,错误返回-1.
参数:
sem:定义的信号量变量的地址;
pshared:如果设置为0,说明这个信号量用于同一个进程的多个线程之间同步的。
如果不为0,则说明这个信号量是在多个进程间共享的。一般应该将其存放在共享内存区。
value:信号量要初始的值(意思也是可用资源的数量)。
2、在使用完信号量之后应该释放与信号量相关的资源。
3.获得资源(P操作)
上面三种情况:
第一种sem_wait通俗点理解,使得信号量的值减一,如果这时的信号变量是0,那么就将该线程/进程挂起等待,也就是阻塞式等待。
第二种sem-trywait是非阻塞等待,如果资源不就绪,那么就返回错误码。
4.释放资源(v操作)
使得信号量的值加1,同时唤醒挂起等待的线程或进程。
返回值:成功返回0,失败返回-1并设置错误码。
描述:
调用该函数可以释放资源(v操作),使得信号量的值加1,同时唤醒挂起等待的线程。
也掌握了生产者与消费者模型的规则,并且实现了基于单链表的生产者与消费者模型,但是我们实现的基于单链表的生产者与消费者模型还是存在问题,存在死锁的问题,如果想深入理解死锁问题的,可以去看下我总结的死锁的博客。
这篇博客我们主要来实现基于环形队列的生产者与消费者模型。
由于上一篇博客已经讲清楚了关于生产者与消费者的各种问题,所以这篇博客我们就直接来实现。
使用环形队列模拟实现不带锁的单生产者与单消费者模型的思路:
生产者与消费者遵循两个规则:
1.消费者永远都在生产者的后面。(如果消费者可以超过生产者的话,那么消费者可能会读取到垃圾数据)。
2.生产者永远不能将消费者包围一圈
(如果生产者的优先级很高,消费者的优先级很低,如果生产者可以将消费者包围一圈,那么生产者可能就会覆盖掉原来的旧数据(消费者还没来得及消费的数据))。
由上面的两条规则可知:
1.当生产者将环形队列写满时,这时生产者会被挂起等待。(等待数据被消费者读取走)。
2.当消费者将环形队列中的数据读取完时,这时消费者就会被挂起等待。(等待写入生产者写入的新的数据)。
实现基于环形队列的生产者与消费者模型(不带锁)
#include<stdio.h> #include<stdlib.h> #include <semaphore.h> int blank[64]; sem_t semBlank;//空格子的信号量 sem_t semData;//数据的信号量 //消费者读数据 void *consumer(void *arg) { //p int step = 0;//每次读取数据的下标 while(1) { sem_wait(&semData);//等待数据信号量(p操作) //下面两行是临界区 int data = blank[step]; printf("consume done... %d\n",data); step++; sem_post(&semBlank);//释放格子资源(v操作) step %= 64;//保证下标不越界 // sleep(1); } } void *producter(void *arg) { int step = 0; while(1) { sem_wait(&semBlank);//等待格子资源(p操作--) int data = rand()%1234; blank[step] = data; printf("product done... %d\n",data); step++; sem_post(&semData);//释放数据资源(v操作++) step %= 64; sleep(2); } } int main() { sem_init(&semBlank,0,64); sem_init(&semData,0,0); pthread_t c,p; pthread_create(&c,NULL,consumer,NULL); pthread_create(&p,NULL,producter,NULL); pthread_join(c,NULL); pthread_join(p,NULL); sem_destroy(&semBlank); sem_destroy(&semData); return 0; }
结果如下:
信号量有关操作函数:
1.用sem_init来初始化一个信号量变量:返回值:
成功返回0,错误返回-1.
参数:
sem:定义的信号量变量的地址;
pshared:如果设置为0,说明这个信号量用于同一个进程的多个线程之间同步的。
如果不为0,则说明这个信号量是在多个进程间共享的。一般应该将其存放在共享内存区。
value:信号量要初始的值(意思也是可用资源的数量)。
2、在使用完信号量之后应该释放与信号量相关的资源。
3.获得资源(P操作)
上面三种情况:
第一种sem_wait通俗点理解,使得信号量的值减一,如果这时的信号变量是0,那么就将该线程/进程挂起等待,也就是阻塞式等待。
第二种sem-trywait是非阻塞等待,如果资源不就绪,那么就返回错误码。
4.释放资源(v操作)
使得信号量的值加1,同时唤醒挂起等待的线程或进程。
返回值:成功返回0,失败返回-1并设置错误码。
描述:
调用该函数可以释放资源(v操作),使得信号量的值加1,同时唤醒挂起等待的线程。
相关文章推荐
- 多线程设计模式Future、Master-Worker和生产者-消费者模型
- [Linux]生产者与消费者 三种模型 C
- Java多线程中的生产者消费者模型
- 简单生产者消费者模型(java实现)
- Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型
- 生产者消费者模型你知道多少
- 阿里面试:生产者消费者模型
- 生产者-消费者模型的Java实现
- JAVA 线程通信以及多个生产者消费者模型
- 传统消费者、生产者模型 syncrinized和Object的wait,notifyAll实现
- 微软100题(34)生产者消费者模型实现队列
- 生产者消费者模型
- 一个简单的C语言操作系统生产者消费者模型
- java实现生产者消费者模型
- ImportNew 首页所有文章资讯Web架构基础技术书籍教程我要投稿更多频道 » 如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例
- pthread-消费者/生产者模型实现
- 生产者/消费者模型、读写模型、线程池
- concurrent-02(实现生产者消费者模型)
- 线程同步之经典生产者-消费者模型
- 生产者-消费者模型的3种Java实现:synchronized,signal/notifyAll及BlockingQueue