zoukankan      html  css  js  c++  java
  • 关于线程同步与双队列性能(转载)

    关于线程同步与双队列性能

    1问题背景

    2第一种方式,共享队列

    3第二种方式,双队列

    4遇到的问题

    关于线程同步与双队列性能

    2009712星期日

    1问题背景

    这是在20083月学习多线程编程时遇到的一个问题。当时我写了一个代码片段,其中两个线程共享一个队列,一个线程往队列中写数据,而另一个线程从队列中读取数据。这是典型的生产者和消费者模型。但在这里并不适合使用semaphore来做。

    由于当时的我对多线程编程不太熟练,在线程中大量使用了printf输出调试信息,printf是典型的IO操作会引起线程的切换,所以打出来的信息也显示了线程切换十分频繁,几乎每一个数据入队列后,就立即被另一个线程抢占,并出队列,队列的长度一直为01,处理效率非常低。

    在本周四,我有一个与架构师讨论问题的机会,我便找架构师请教了这个问题。当时我给架构师描述了我的问题,也许是我自己基础不好,架构师并不能很好的理解我的意思,但架构师根据我的描述给了我一些意见:

    1、  如果是两个线程交互,那么除了加锁之外,还可以使用原子操作(atom)来代替。

    2、  如果两个线程共享同一个队列,无可避免的就是其中一个线程的在操作这个队列时,另外一个只能等着,效率很低。建议采用双队列技术,可以提高并行效率。这一点在后面的实验中得到证实,使用双队列技术后效率提高了一个数量级!

    3、  操作系统一般10ms-20ms调度一次,所以应该尽量避免加锁,因为加锁会陷入内核。增加开销。

    4、  尽量避免使用printf这种同步IO,建议分配一个大的缓冲,用于存储输出信息,在写满后一次性输出取出,这样就避免频繁的阻塞线程,导致调度频繁。

    根据架构师的建议,我在公司里完成了这个程序,使用了两种方式:共享队列和双队列。

    2第一种方式,共享队列

    两个线程共享一个队列,一个往里写,一个往外读,我将写入数据的那个线程叫做writer,读出数据的那个线程叫做reader。这样,writer线程在工作时,reader线程只能等待,reader线程在工作时写线程只能等待。有人会说,可以多来几个reader这样可以使用RWLOCK,但根据应用场景,这里就只有一个消费者。这是一种最简单的方式,也是最基本的方式,效率也很低。在这里就不再讨论这个方式的实现了。

    3第二种方式,双队列

    两个线程各自一个队列,writer线程往队列1写数据,reader线程从队列2读数据,而在队列2为空时,我将队列1中的数据拼接或交换到队列2中,这样只有这个短暂的交换或拼接动作需要加锁。

    那么这里还有个问题,当队列1中有多少数据后拼接到队列2的效率是最高的呢?架构师给了一个建议,先以16个、32个、64个这样的步进进行测试,直到找到性能最好的队列拼接长度。而我最后没有使用架构师给出的这个建议,而是模拟内核与用于空间之间的网络读写接口,这样就把这个任务给了系统调度,大概策略如下:

    1、  如果reader线程发现队列2和队列1中都没有数据,则陷入内核睡眠状态,等待event唤醒。

    2、  Writer线程当往队列1中写数据时,发现队列1和队列2都没有数据,则认为reader线程肯定会等待在event上,则向reader线程出发event。由于操作系统规则,event类似于condition variable,不会马上被唤醒。所以writer有机会往队列1中继续写入一些数据,其实在多核CPU情况下,writer一直可以往队列1中写数据,除非队列1reader线程锁住。

    3、  Reader线程被event唤醒之后,会干以下事情

    a)         如果队列2是空的,那么就锁住队列1和队列2,然后将队列1中的数据一次性拼接到队列2中。

    b)        Reader线程开始读取队列2中的数据,这里需要注意的是如果是多核CPU,这时writer线程可能正在往队列1中写数据,这与reader线程处理是完全并行的,互不相干,所以双队列在多核CPU上效率很高。

    c)         如果reader线程将队列2读空之后,发现writer线程已经又向队列1中写入了一些数据,那么从步骤a)开始重复执行。

    d)        如果reader线程将队列2读空之后,发现队列1也是空的,那么说明没有数据了,这时reader线程又回到event上睡眠,等待writer线程的event通知。

    根据测试双队列的性能后,发现比共享队列的性能高一个数量级(10倍),这些测试数据在公司里的Intel P4 HT 3.0G 1.5GMEM上测试的出来的,而本文实在家里写的,所以数据没有在这里给出。

     

  • 相关阅读:
    js鼠标事件/onclick/鼠标点击/光标移开
    搭建PHP环境
    SQL语法的一些整理
    DataTime格式大全啊!
    分页存储过程
    jquery中获取键盘按键
    中国历史朝代歌(完整)
    js键盘事件
    js鼠标、键盘事件实例代码
    《.NET Compact Framework移动开发指南》答疑一
  • 原文地址:https://www.cnblogs.com/qwcbeyond/p/2042433.html
Copyright © 2011-2022 走看看