《多处理器编程的艺术》读书笔记(7)--- CLH队列锁

      ALock并发线程的最大个数为一个已知的界限N,同时也要为每个锁分配一个与该界限大小相同的数组。 就算一个线程每次只访问一个锁,同步L个不同对象也需要O(LN)大小的空间。

CLHLock

ContractedBlock.gif ExpandedBlockStart.gif Code
 1 public class CLHLock : ILock
 2 {
 3     private class QNode
 4     {
 5         public bool Locked { getset; }
 6     }
 7 
 8     private QNode tail;
 9 
10     [ThreadStatic]
11     private static QNode myPred;
12 
13     [ThreadStatic]
14     private static QNode myNode;
15 
16     public CLHLock()
17     {
18         tail = new QNode();
19     }
20 
21     public void setLock()
22     {
23         myNode = new QNode();
24         myNode.Locked = true;
25         myPred = Interlocked.Exchange<QNode>(ref tail, myNode);
26         while (myPred.Locked) { }
27     }
28 
29     public void unlock()
30     {
31         myNode.Locked = false;
32         myNode = myPred;
33     }
34 }

       类QNode的布尔型Locked属性记录了每个线程的状态。如果Locked为true,则对应的线程要么已经获得到锁,要么正在等待锁;如果Locked为false,则对应的线程已经释放了锁。线程被顺序地排入“隐式”链表,每个线程通过一个线程局部变量myPred指向前驱线程,公共的tail保存着最近加入到队列的结点。

      若要获得锁,线程将自己的myNode的Locked设为true,表示该线程准备获得锁。随后线程对tail调用Interlocked.Exchange方法,把自身的前驱myPred指向队尾,并将自身设置为新队尾。最后线程就在myPred的Locked上旋转,直到myPred释放锁。若要释放锁,线程将其Locked设为false。

      CLHLock让每个线程在不同的存储单元上旋转,这样当一个线程释放它的锁时,只能使其后继的cache无效。该算法比ALock所需要的空间少(同步L个不同对象只需要O(L + N)的空间),且不需要知道可能使用锁的线程数量。也提供了先来先服务的公平性。

转载于:https://www.cnblogs.com/pennant/archive/2009/10/23/1588904.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值