1.ReetrantLock —— 實現(xiàn)原理:
實際組成:
獲取到鎖的:首先將status置為1,再一次獲取這個鎖的時候,在這個status上進(jìn)行++的操作。
沒有獲取到鎖的:有一個雙向鏈表,進(jìn)來的線程都掛在這個鏈表的尾部,保持頭指針為null
加鎖過程:
線程 1,2,3進(jìn)來,可以選擇公平鎖和非公平鎖的實現(xiàn)方式。
1)首先通過CAS去置位
if 成功則占有鎖
標(biāo)記自身占有鎖,把state置為1
else
再去嘗試 2)。
2)去獲取一個state
if (state ==0)
執(zhí)行1)
else if(state>0 && 占有的線程是當(dāng)前線程)
state++;
else
沒有占有到鎖
3) 將自己放入一個等待的FIFO的隊列
if(隊列的尾節(jié)點==null)
初始化,直接放入尾節(jié)點
else(不為空){
將上一個節(jié)點的next指向該節(jié)點,使該節(jié)點成為新的尾節(jié)點
if(當(dāng)多個節(jié)點去占有尾節(jié)點){
whlie(每個線程放進(jìn)隊列里){
使用CAS去占有尾節(jié)點
}
}
}
4 if(當(dāng)前節(jié)點的頭結(jié)點為Null){
獲取鎖
if(失敗){
waitStatus == SIGNAL;
該線程掛起;
遞歸去掛起后面的等待節(jié)點的線程,都是將每個節(jié)點對應(yīng)的waitStatus置為SIGNAL;
}
}
注意:
AQS的FIFO的等待隊列給解決在鎖競爭方面的羊群效應(yīng)問題提供了一個思路:保持一個FIFO隊列,隊列每個節(jié)點只關(guān)心其前一個節(jié)點的狀態(tài),線程喚醒也只喚醒隊頭等待線程。
參考:
https://blog.csdn.net/yanyan19880509/article/details/52345422
http://www.importnew.com/24006.html
https://blog.csdn.net/jiangjiajian2008/article/details/52226189