zoukankan      html  css  js  c++  java
  • 实现一个双缓冲队列

    在生产者-消费者模式中,我们常常会使用到队列,这个队列在多个线程共享访问时存在互斥和竞争操作, 意味着每次访问都要加锁。如何更好的如何减少锁竞争次数呢 ?今天要介绍的双缓冲队列就是个不错的选择。

    双缓冲队列就是冲着同步/互斥的开销来的。我们知道,在多个线程并发访问同一个资源的时候,需要特别注意线程的同步问题。稍稍不注意,噢货,程序结果不正确了。

    原理

    直接上图:

    img

    在双缓冲队列中,锁除了起到保护数据安全的作用来,还要承担线程调度的任务。

    • 双队列交换位置和任务入队列都需要对当前队列进行操作,因此,他们是互斥的操作。
    • 消费操作放在单独的线程中,在没有任务进来时,需要将线程置为等待状态。

    使用两个信号量,来调度入列队和交换队列的操作。同时,我们还需要一个信号量,在没有任务入队列时,阻塞整个消费线程。

    主要使用 AutoResetEvent,ManualResetEvent,它们的具体使用可以看一下园子里的文章:

    http://www.cnblogs.com/springyangwc/archive/2011/10/12/2208991.html

    1. AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待,也就是说AutoResetEvent一次只唤醒一个线程;
    2. ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送;
    3. 也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。

    实现

    我以一个简单的示例来演示整个过程。

    在生产线程中,入队列一些字符串;使用消费线程,把这些字符串和它所在队列编号打印出来:

    img

    img

    看一下运行效果:

    img

    可以看到,在消费线程中,队列交换使用。

    下一篇,我们来实现一个对双缓冲队列的封装。

  • 相关阅读:
    cf D. Vessels
    cf C. Hamburgers
    zoj 3758 Singles' Day
    zoj 3777 Problem Arrangement
    zoj 3778 Talented Chef
    hdu 5087 Revenge of LIS II
    zoj 3785 What day is that day?
    zoj 3787 Access System
    判断给定图是否存在合法拓扑排序
    树-堆结构练习——合并果子之哈夫曼树
  • 原文地址:https://www.cnblogs.com/cqgis/p/6403262.html
Copyright © 2011-2022 走看看