AQS的思想(穩定思想):即使确定了正常節點,這個節點也可能下一秒異常,即使找到了正常節點,這個節點可能隻是異常status=0/-1的節點,這些都不要緊,都隻是在自己旋轉‘生命周期’裡面和自己所看到的 最大可能的保證隊列的穩定狀态,如果判斷錯了,其他節點會幫着處理直到隊列真正的穩定。
AQS的思想(出隊思想):通過head=-1出隊,head=0出隊失敗(外部線程不會再次調用head出隊)後面節點就要自行出隊。(unlock方法會被沒有進入隊列搶到了鎖的線程調用,隊列中擷取到鎖的線程執行完之後也會調用)
隊列走向穩定時候,是多個節點線程在調節某一個節點,并且還有一個出隊的線程在調節head。
ReentrantLock#AQS是一個FIFO的隊列,通過head來出隊,通過taill入隊。
- 隊列穩定狀态
- 隊列處于沒有穩定的中間态
- 隊列穩定時候出隊
- 隊列沒有穩定時候出隊。
節點狀态分為:正常status=-1/0,異常status=0/-1,異常status=1。Head節點一定是正常節點(status=0/-1,不可能=1,因為如果頭結點擷取鎖後異常了,頭節點.prev=null,在cancelAcquire方法裡面執行while (pred.waitStatus > 0)就會抛出異常,整個代碼都無法執行了)。區分節點是不是正常判斷标準是status值(線程異常了隻能通過節點的狀态才能看出來,是以肯定有錯誤,都是盡可能的保證隊列的穩定性,後面見到)。也就是說 異常status=0/-1跟正常節點是一樣的,能夠被作為前驅并且通過它也能夠出隊後面的節點(作為前驅不要緊,關鍵在于能不能像正常節點一樣喚醒後面出隊),因為head喚醒 異常status=0/-1節點時候跟喚醒正常節點一樣能夠再次去喚醒後面的節點(不會導緻隊列出不了隊,異常status=0/-1節點線程裡面的執行邏輯會自動判斷去喚醒)。head喚醒 異常status=1節點時候可能不能夠再次去喚醒後面的節點(因為status=1節點可能不會再去執行喚醒的代碼)。
隊列穩定狀态(能夠正常出隊):
前驅:回路中前面status正常節點
後驅:回路中後面status正常節點
每2個正常節點構成前驅後繼關系,兩兩相連是正常節點,其餘不管,或者中間有異常節點:
達到穩定的中間狀态:
調整都是以栅欄作為邊界的,2個status正常節點中間不會再有statsu正常節點。每個節點都隻保證自己前面的隊列是穩定的,不管後面的。
Status正常不一定是正常節點,但是在做正常節點調整法的一定是正常節點,status異常一定是異常節點。
隊列走向穩定狀态時候:
真正正常節點調整方法:1找前驅status正常節點,2和這個節點建立後驅關系,2設定這個節點=-1。然後自己阻塞,自己阻塞之後前驅節點異常了不管了。
異常節點調整方法:1找前驅status正常節點 2設定自己=1 3幫助建立後驅關系 4自己.next=自己。 建立後驅關系之後前驅節點異常了不管了。
結論1:從前往後找,可能斷開,如果不是因為自己.next=自己,那麼從前往後也能找到所有的正常節點和部分異常節點。從後往前找,可以找到所有的status正常的節點,并且還會找到部分status異常節點。
結論2:真正正常節點‘生命周期’裡面 開始旋轉 到确定找到正常前驅那個時間點 再到阻塞,異常節點‘生命周期’裡面 開始旋轉到 确定正常前驅 再到退出,都是盡可能的建立正确的前驅後繼關系 把隊列變成穩定狀态,自己阻塞了或者異常退出了 前驅後繼關系不正确了 就不管了了,交給其他還在旋轉的節點去處理。
AQS的思想(個人總結):即使确定了正常節點,這個節點也可能下一秒異常,即使找到了正常節點,這個節點可能隻是異常status=0/-1的節點,這些都不要緊,都隻是在自己旋轉‘生命周期’裡面和自己所看到的 最大可能的保證隊列的穩定狀态,如果判斷錯了,其他節點會幫着處理直到隊列真正的穩定。
隻有節點都阻塞了,異常節點都退出了,隊列才是真正的穩定。
這些都是中間狀态。
規律:
1 每個節點隻受後面節點影響
2 prev隻有自己修改,沒有多線程問題
3 status正常的節點的next受到後面一個真正正常調整方法和多個異常節點調整方法修改指向後面真正正常節點,
4 Status異常的節點的next隻有自己修改
5 status正常的節點的status受到後面一個真正正常和多個異常修改=-1。Status異常的節點的status隻有自己修改=1
再看幾張圖: