科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道C#中的ReaderWriterLock和LockFree

C#中的ReaderWriterLock和LockFree

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

作者:中国IT实验室 来源:中国IT实验室 2007年9月8日

关键字: LockFree Writer READER C#

  • 评论
  • 分享微博
  • 分享邮件
 前一阵在一个project中使用了ReaderWriterLock,发现了两个问题:

  Performance非常差

  UpgradeToWriterLock并不是atomic的从ReaderLock转换到WriterLock,而是等同于"lock.ReleaseReaderLock(); lock.AcquireWriterLock();".这样的semantics有一定的迷惑性,我开始的时候也认为这个operation是atomic的,等出现bug并debug了很久才发现原来如此。不过经过认真的思考,发现这其实不是。NET designer的错,根本没办法把这个operation设计成atomic的。原因如下:

  很多个thread同时acquire到了ReaderLock,

  他们都call UpgradeToWriterLock,如果这个operation是atomic的,那么没有哪个thread能upgrade成功。

  后来我干脆不用ReaderWriterLock了,直接换成了LockFree的方法。这个得益于ibm的一些paper.(http://www.research.ibm.com/people/m/michael/pubs.htm

  在C#中实现LockFree其实是很简单的,因为有了Garbage Collection,

  code:

 1     class LockFreeDictionary<Key, Value>
 2     {
 3         private Dictionary<Key, Value> m_dict = new Dictionary<Key, Value>();
 4
 5         public Value Lookup(Key key)
 6         {
 7             return m_dict[key];
 8         }
 9
10         public void Update(Key key, Value value)
11         {
12             Dictionary<Key, Value> newDict = null;
13             Dictionary<Key, Value> oldDict = null;
14             do
15             {
16                 oldDict = m_dict;
17                 newDict = new Dictionary<Key, Value>(oldDict);
18                 newDict[key] = value;
19             } while (Interlocked.CompareExchange<Dictionary<Key, Value>>(ref m_dict, newDict, oldDict) != oldDict);
20         }
21     }
22

  解释如下:

  line 16, keep a reference to the original Dictionary object,

  line 17, construct a new Dictionary object base on original object. For oldDict, this step is readonly, and doesn't need lock,

  line 18, perform the update operation upon the new constructed object,

  line 19, try to swap the new object into the original one. If the return value of Interlocked.CompareExchange operation is NOT equal to oldDict, it means during this do-while block executation, there is another thread changed m_dict. In this scenario, we need to do the update again.

  the swapped out object (oldDict) can be collected by Garbage Collection.

  if we want to use LockFree data structure in C++, there is another technique called Hazard Pointer. it's in the ibm research papers.

  不过不是什么情况都可以使用这种LockFreeDictionary的,,不然你会得到相反的效果(performance很差),这里的scenario是read非常多,write非常少。 不过这种情况也挺常见的。

  这种方法的好处是在Lookup的时候没有任何lock,从而极大的提高了performance.(我的project里面比ReaderWriterLock提高了2000倍,)

  对LockFree有研究的或者有兴趣的可以留言大家讨论讨论,:)

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
          邮件订阅

          如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

          重磅专题
          往期文章
          最新文章