画图趣解CLH锁的实现原理

    面试题上看到CLH锁的实现原理,想找视频看看没找到,各种博客写的也很抽象,缺乏形象感不易理解。于是就自己写一个,争取做到通俗易懂。

    CLH锁是自旋锁的一种实现方式 (java自旋锁的4种实现方式),实现了自旋锁的公平性,即按照请求锁的时间先后顺序来获取锁。之所以叫CLH锁, 是因为它的作者是Craig,Landin andHagersten,取他们的名字首字母而命名的。


CLH锁的类结构图

 

    CLHLock可以创建节点QNode, QNode中有一个boolean变量locked,它的作用是表示自己是否有“需求”

    CLHLock有两个ThreadLocal变量,myNode 用来指向当前节点,myPred用来指向当前节点的前驱节点;

    还有一个AtomicReference变量tail用来标示List的尾部位置,大家排队的话都自觉从尾部往后排。


    下面线程们都来获取锁啦!

   (1)

首先来的是Thread1,它上来要先创建一个QNode,并且把locked置为 true,大声宣布自己对锁有需求,在自己完成想干的事之前,是不会把locked置为false的。

    然后它就去找tail ,并且把tail 的标志拿在自己手里,表示自己是队列的尾部,谁要是对锁也有需求,通通到我身后排队去。  “哟,我前面没人!没事,就当有人!” 只要把myPred 向前指就行了!(myPred=NULL)因为thread1前面没有人,所以thread1就拿到锁了,如下图

  然后thread1占着锁,开始忙自己的事。

 (2)

这时, thread2来了,表示自己对锁也有需求,locked置为true,然后就找 tail 的位置,在后面排队。thread2一看,thread1已经占着锁了,于是他就一直盯着 thread1 的QNode状态 locked 自旋

  while(thread1. locked == true){}

 然后将自己的前一个节点myPred 指向 thread1的 myNode,就等着 thread1 的locked变成 false好去拿锁。

 因为thread2 排在了 thread1 之后,所以现在thread2才是队伍的末尾,所以 tail 气球就传到了 thread2手里,后面再来排队就要排到thread2后面了。 如下图:

(3)

  这时thread1忙完了,需求解决了,于是他将 locked 置为 flase,一直盯着thread1的locked标志自旋的thread2就拿到了锁。 thread1 将自己的QNode销毁, 于是thread2的myPred就指向了null, 与之前thread1的处境是一样一样的! 后面再有thread3到thread2后面排队,跟之前的过程也是一样一样的!如下图

  这样,就实现了先到先得的公平CAS。代码实现看文中链接, 理解了原理再去看代码应该很容易了。

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章