并发基础 -- 生产消费者模型
2009-03-15 11:23
162 查看
案例:
请编写一个producer线程和一个consumer线程,两个线程共享一个固定长度的缓冲区和缓冲区上的一个读写索引index。producer负责把一些随机数写到缓冲区,consumer负责删除那些随机数。
分析:
1 如果不用并发技术,主要弊病是没有对缓冲区进行保护,因此,如果producer在index尚未更新之前把随机数写入缓冲区,就会覆盖以前的内容,让consumer读到错误数据。此外,对index位于缓冲区最后一个元素位置上时的更新操作考虑不周,扰乱producer和consumer的配合。
2 执行效率问题。如果producer比consumer慢很多,Consumer会陷入“忙等待(busy waiting)”状态(苏醒->什么都不作->再休眠),是对资源的一种浪费。原则上讲,只有在有东西可消费的时候才应该让consumer苏醒;同样,只有当缓冲区里有空缺的时候才应该让producer苏醒。
3 大部分人选择了由调用者来加锁:作为生产者,往缓冲区里插入数据时,先加锁,插入数据,然后解锁。作为消费者,从缓冲区里取数据时,先加锁,删除数据,然后解锁。这是合理的,不过有点麻烦:每个调用者都要做这些动作,如果其中一个调用者忘记了解锁的步骤,就会造成死锁。而且调用者必须要清楚自己是在多线程下工作,这些代码放到单线程的环境中就不能使用了。在很多情况下由实现者来加锁是比较好的选择,那样对调用者更为友好,可以避免出现一些不必要的错误。比如像目前Linux下流行的DBUS,它是一套进程间通信框架,它支持单线程和多线程版本,但调用者不需要明确加锁/解锁,也不需要连接不同的库或者用宏来控制,单线程版本和多线程版本的不同只是在一个初始化函数上。
1) 支持多线程和单线程版本。对于多线程版本,由实现者(在缓冲区)加锁/解锁,对于单线程版本,其性能不受影响(很小)。
2) 区分单线程版本和多线程版本时,不需要链接不同的库,或者要宏来控制,完全可以在运行时切换。
3) 保持缓冲区的通用性,不依赖于特定的平台。
解决办法:
1
2
3
请编写一个producer线程和一个consumer线程,两个线程共享一个固定长度的缓冲区和缓冲区上的一个读写索引index。producer负责把一些随机数写到缓冲区,consumer负责删除那些随机数。
分析:
1 如果不用并发技术,主要弊病是没有对缓冲区进行保护,因此,如果producer在index尚未更新之前把随机数写入缓冲区,就会覆盖以前的内容,让consumer读到错误数据。此外,对index位于缓冲区最后一个元素位置上时的更新操作考虑不周,扰乱producer和consumer的配合。
2 执行效率问题。如果producer比consumer慢很多,Consumer会陷入“忙等待(busy waiting)”状态(苏醒->什么都不作->再休眠),是对资源的一种浪费。原则上讲,只有在有东西可消费的时候才应该让consumer苏醒;同样,只有当缓冲区里有空缺的时候才应该让producer苏醒。
3 大部分人选择了由调用者来加锁:作为生产者,往缓冲区里插入数据时,先加锁,插入数据,然后解锁。作为消费者,从缓冲区里取数据时,先加锁,删除数据,然后解锁。这是合理的,不过有点麻烦:每个调用者都要做这些动作,如果其中一个调用者忘记了解锁的步骤,就会造成死锁。而且调用者必须要清楚自己是在多线程下工作,这些代码放到单线程的环境中就不能使用了。在很多情况下由实现者来加锁是比较好的选择,那样对调用者更为友好,可以避免出现一些不必要的错误。比如像目前Linux下流行的DBUS,它是一套进程间通信框架,它支持单线程和多线程版本,但调用者不需要明确加锁/解锁,也不需要连接不同的库或者用宏来控制,单线程版本和多线程版本的不同只是在一个初始化函数上。
1) 支持多线程和单线程版本。对于多线程版本,由实现者(在缓冲区)加锁/解锁,对于单线程版本,其性能不受影响(很小)。
2) 区分单线程版本和多线程版本时,不需要链接不同的库,或者要宏来控制,完全可以在运行时切换。
3) 保持缓冲区的通用性,不依赖于特定的平台。
解决办法:
1
2
3
相关文章推荐
- 并发控制(8)使用executor并发框架来实现的生产消费者模型
- java线程:并发协作的经典之生产消费者模型
- JAVA基础——多线程同步实现(生产者/消费者模型)
- Java线程:并发协作-生产者消费者模型
- Python之Queue模块以及生产消费者模型
- 并发无锁队列学习(单生产者单消费者模型)
- C++11 并发指南九(综合运用: C++11 多线程下生产者消费者模型详解)
- 深入学习java并发编程:内存模型(一)基础
- Java线程:并发协作-生产者消费者模型
- 并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法 在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列(先进先出)。
- 11.python并发入门(part8 基于线程队列实现生产者消费者模型)
- 生产与消费者三种模型
- 并发协作-生产者消费者模型
- 并发协作-生产者消费者模型
- 并发协作-生产者消费者模型
- Java并发协作——生产者、消费者模型
- Java高并发程序-Chapter2 Java并行程序基础 (第六讲)volatile 与 Java 内存模型 JMM
- 生产消费模型-多生产者vs多消费者
- JavaSE 基础 第62节 生产者消费者模型
- java生产者消费者模型(线程协作)