畫圖趣解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。代碼實現看文中鏈接, 理解了原理再去看代碼應該很容易了。

 

 

 

 

 

 

 

 

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