1. Lock
互斥的,在請求鎖時如果該鎖別其它線程獲取的時候,該線程將會被阻塞,放在該鎖的阻塞隊列中,當線程釋放鎖時,被阻塞的線程會被激活來判斷是否是阻塞隊列的頭結點將會獲得鎖,依次下去。
其中的阻塞隊列是FIFO隊列,這也是最簡單的線程調用策略了。
2. 可重入鎖(ReentrantLock)
相對於Lock,可重入鎖式支持同一個線程獲取鎖的。列入遞歸方法,在方法中還可以調用該方法的。
但是Lock不支持重入,會出現線程被自己阻塞的情況。(當前線程正在運行,當該線程請求鎖時,返回的false,這樣改線程會被阻塞,這樣正在運行的該線程也會被阻塞)
重點知識
- 如何實現可重入
- 如何實現公平性(原則是:現請求鎖的線程,先獲得鎖)
公平性
公平
其實就是按照FIFO的原則,每次在等待隊列的頭部獲取線程來得到鎖
- 性能比較低,因爲每次都要切換
非公平
-
默認是非公平的
-
相比於公平,非公平性能更高,但是可能會產生死鎖。
3. 讀寫鎖
將排他鎖分成讀寫鎖,也就是將讀操做和寫操作分開控制。
同一時刻可以允許多個讀鎖,但是當又寫鎖時,其它所有的讀寫操做都要被阻塞,當該讀鎖釋放時,被阻塞的讀寫操做才恢復。這樣保證數據的一直性,保證不會出現髒讀的情況。
特點
-
公平性
-
可重入性
-
鎖降級(寫鎖可以降級爲讀鎖)
4. ReentrantReadWriteLock
讀寫狀態的設計
通過將32位整形變量分成高16位和低16位,高16位爲寫狀態,低16位爲讀狀態。
通過位操作來實現對讀寫狀態的維護
寫鎖的獲取與釋放
寫鎖的獲取與釋放和Lock很類似,因爲寫鎖其實也會是排他鎖。同一時刻只有唯一的一個寫操作獲取寫鎖。
讀鎖的獲取與釋放
鎖降級
先獲取讀鎖,準備好寫入的數據,在獲取讀鎖,這樣就實現了從寫鎖到讀鎖的降級。
- 爲什麼不直接釋放寫鎖呢?還要獲取讀鎖,這樣講避免,釋放寫鎖之後,其他線程獲取寫鎖將數據更改,但是當前線程是感知不到這種變化的。如果獲取讀鎖,要獲取讀鎖的線程將會被阻塞,這樣就避免了這種情況。