码迷,mamicode.com
首页 > 其他好文 > 详细

双缓冲List

时间:2016-07-07 12:37:29      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:

前言

声明:本文从Enode之父汤雪华QQ群里提取的,分享给各位小伙伴们供参考。

  双缓冲,顾名思义为两个List,此设计用于解决收发分离过程中最大限度避免锁的竞争、有效的降低CPU开销、降低锁的竞争冲突而生。


应用场景

  双缓冲List的设计思路,应用在多线程产生消息,单线程处理消息的场景。


 

设计思路

  声明2个list,分别为_requestsWrite,_requestsRead,写入的消息放入_requestsWrite,读取从_requestsRead读取;

  再声明一个bool类型的_hasNotified,false表示_requestsWrite里没消息,true表示_requestsWrite有消息。通过_hasNotified判断是否需要交换引用地址。

  再声明一个int类型的_requestsWriteThreshold,这个值可以根据自己的场景进行配置,如果没有这种阈值的设计,那如果_requestsRead处理慢,而_requestsWrite增长很快,那_requestsWrite很快就满了,把内存撑爆了。

  消息接收后都放入_requestsWrite,通过lock解决并发问题,里面不是写文件,而是把消息先放入_requestsWrite中,这个动作非常快,所以lock的竞争开销很小;消息持久化采用单线程while(true){……}的方式,然后通过SpinWait.SpinOnce来避免CPU空转。核心思路就是把接收的数据先放入_requestsWrite,然后要处理的数据放入_requestsRead,处理总是面向_requestsRead并单线程处理;每次处理是判断_requestsWrite里是否有数据,如果有就和_requestsRead交换引用,然后处理_requestsRead;

  如果处理_requestsRead的线程处理太慢,来不及处理,则我们只需要给_requestsWrite的容量设置一个阈值即可,即当_requestsWrite到达阈值时,就自动流控。

  StoreMessageAsync是放入写_requestsWrite。

  PersistMessages()这个方法是单线程运行,此方法主要职责是从_requestsRead里取要写入文件的所有消息,在一个while(true)里被调用,写的时候,总是一次性把_requestsRead里的所有消息都写入磁盘。写完后,再看看_hasNotified是否为true,如果是,则和_requestsWrite进行交换,然后继续写。一开始放入写list后,总是检查_hasNotified是否为false的,如果是false,就立即改为true

  SwapRequests就是双缓冲队列的核心设计,负责交换地址。

 技术分享

技术分享

技术分享 

双缓冲List

标签:

原文地址:http://www.cnblogs.com/sunbinglong/p/5649441.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!