多线程系列之生产者和消费者问题

摘要:
生产者和消费者将继续有序地交叉。然后,我们将增加这个简单的生产者和消费者问题的难度。将使用者数更改为2,将缓冲池更改为具有4个缓冲区的大型缓冲池。最后,生产者和消费者的问题总结如下:1。首先,考虑缓冲操作中生产者和消费者的相互排斥。2.无论有多少生产者和消费者,缓冲池中都有多少缓冲区。正确把握解决生产者和消费者问题的方法是开发商的基本素质之一。

  生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,显然生产者和消费者之间必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经放入产品的缓冲区中再次投放产品。

  首先来简化问题,先假设生产者和消费者都只有一个,且缓冲区也只有一个。这样情况就简便多了。

    第一.从缓冲区取出产品和向缓冲区投放产品必须是互斥进行的。可以用互斥锁来完成。

    第二.生产者要等待缓冲区为空,这样才可以投放产品,消费者要等待缓冲区不为空,这样才可以取出产品进行消费。并且由于有二个等待过程,所以要用二个事件或者信号量来控制。

在.net中,用Monitor可以同时达到以上两者的效果。演示如下:

1 首先,声明一个队列:

 _queue = new Queue<T>();

2 设置缓冲区大小:

int _maxQueueCount=1024;

3 用两个变量来记录生产者和消费者的数量:

  int _consumersWaiting;
  int _producersWaiting;

4 生产者生产:

       lock (_locker)
            {
                _queue.Enqueue(item);
                while (_queue.Count >= _maxQueueCount && !_isDisposed)
                {
                    _producersWaiting++;
                    Monitor.Wait(_locker);
                    _producersWaiting--;
                }
                if (_consumersWaiting > 0)
                    Monitor.PulseAll(_locker);
            }

生产者在队列的长度大于缓冲区之后,释放锁并进入等待状态,同时通知消费者。

5 消费者开始消费:

 lock (_locker)
 { 
 //消费所有数据
  if (_producersWaiting > 0)
         Monitor.PulseAll(_locker);
    _consumersWaiting++;
     Monitor.Wait(_locker);
     _consumersWaiting--;
}

消费者在消费完缓冲区所有数据之后,通知生产者,释放锁,并进入等待状态。

这个时候,生产者重新得到锁,并继续生产。

生产者与消费者变会一直有序的交叉进行下去。

然后再对这个简单生产者消费者问题加大难度。将消费者改成2个,缓冲池改成拥有4个缓冲区的大缓冲池。

请读者自行研究解决办法。

最后,关于生产者和消费者的问题,总结如下:

1.首先要考虑生产者与消费者对缓冲区操作时的互斥。

2.不管生产者与消费者有多少个,缓冲池有多少个缓冲区。都只有二个同步过程——分别是生产者要等待有空缓冲区才能投放产品,消费者要等待有非空缓冲区才能去取产品。

正确掌握生产者和消费者问题的解决办法,为开发人员的一种基本素质之一。当然Coding依然是真正掌握的不二法门:)

免责声明:文章转载自《多线程系列之生产者和消费者问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇EMF介绍系列(六、自定义命令)ROS学习之启动文件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Python多进程与多线程

1、基本概念 2、多线程内容方法 3、多进程内容方法 1、基本概念 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流, 一个进程中可以并发多个线程,每条线程并行执行不同的任务。A thread is an execution context,...

Java 并发系列之七:java 阻塞队列(7个)

1.基本概念 2.实现原理 3.ArrayBlockingQueue 4.LinkedBlockingQueue 5.LinkedBlockingDeque 6.PriorityBlockingQueue 7.DelayQueue 8.SynchronousQueue 9.LinkedTransferQueue 10.小总结 11.t...

如何通过线程池异步调用

生产者-消费者模式在系统交互方面,有几个特点: 1、系统解耦 2、解决并发问题 3、不需要关心对方系统何时处理数据,处理结果如何 下面用几个简单例子逐步说明。 简单例子 假设有两个系统,A系统和B系统,B系统需要依赖A系统产生的数据,也就是说,A系统产生数据后,必须把数据扔给B系统。 这个时候,可以让B系统提供一个方法,比如说提供一个http接口sen...

C语言之生产者与消费者模型

多线程并发应用程序有一个经典的模型,即生产者/消费者模型。系统中,产生消息的是生产者,处理消息的是消费者,消费者和生产者通过一个缓冲区进行消息传递。生产者产生消息后提交到缓冲区,然后通知消费者可以从中取出消息进行处理。消费者处理完信息后,通知生产者可以继续提供消息。 要实现这个模型,关键在于消费者和生产者这两个线程进行同步。也就是说:只有缓冲区中有消息时,...

rabbitmq、kafka、activemq、rocketmq之间对比,区别

rabbitmq、kafka、activemq、rocketmq之间对比,区别 支持原创  转自 https://www.cnblogs.com/williamjie/p/9481780.html 为什么写这篇文章? 博主有两位朋友分别是小A和小B: 小A,工作于传统软件行业(某社保局的软件外包公司),每天工作内容就是和产品聊聊需求,改改业务逻辑。再不然...

启动dubbo消费端过程提示No provider available for the service的问题定位与解决

文/朱季谦 某次在启动dubbo消费端时,发现无法从zookeeper注册中心获取到所依赖的消费者API,启动日志一直出现这样的异常提示 Failed to check the status of the service com.fte.zhu.api.testService. No provider available for the service c...