鎖:可重入鎖 可中斷鎖 公平鎖 讀寫鎖
轉自:http://www.cnblogs.com/wihainan/p/4762800.html 侵刪
1.可重入鎖
如果鎖具備可重入性,則稱作為可重入鎖。
像synchronized和ReentrantLock都是可重入鎖,可重入性在我看來實際上表明瞭鎖的分配機制:
基於執行緒的分配,而不是基於方法呼叫的分配。
舉個簡單的例子,當一個執行緒執行到某個synchronized方法時,比如說method1,而在method1中會呼叫另外一個synchronized方法method2,
此時執行緒不必重新去申請鎖,而是可以直接執行方法method2。
class MyClass {public synchronized void method1() { method2(); } public synchronized void method2() { } }
上述程式碼中的兩個方法method1和method2都用synchronized修飾了,
假如某一時刻,執行緒A執行到了method1,此時執行緒A獲取了這個物件的鎖,而由於method2也是synchronized方法,假如synchronized不具備可重入性,此時執行緒A需要重新申請鎖。
但是這就會造成一個問題,因為執行緒A已經持有了該物件的鎖,而又在申請獲取該物件的鎖,這樣就會執行緒A一直等待永遠不會獲取到的鎖。
而由於synchronized和Lock都具備可重入性,所以不會發生上述現象。
2.可中斷鎖
可中斷鎖:顧名思義,就是可以相應中斷的鎖。
在Java中,synchronized就不是可中斷鎖,而Lock是可中斷鎖。
如果某一執行緒A正在執行鎖中的程式碼,另一執行緒B正在等待獲取該鎖,可能由於等待時間過長,執行緒B不想等待了,想先處理其他事情,我們可以讓它中斷自己或者在別的執行緒中中斷它,這種就是可中斷鎖。
在前面演示lockInterruptibly()的用法時已經體現了Lock的可中斷性。
3.公平鎖
公平鎖即儘量以請求鎖的順序來獲取鎖。比如同是有多個執行緒在等待一個鎖,當這個鎖被釋放時,等待時間最久的執行緒(最先請求的執行緒)會獲得該所,這種就是公平鎖。
非公平鎖即無法保證鎖的獲取是按照請求鎖的順序進行的。這樣就可能導致某個或者一些執行緒永遠獲取不到鎖。
在Java中,synchronized就是非公平鎖,它無法保證等待的執行緒獲取鎖的順序。
而對於ReentrantLock和ReentrantReadWriteLock,它預設情況下是非公平鎖,但是可以設定為公平鎖。這一點由建構函式可知:
1 2 public ReentrantLock() { 3 sync = new NonfairSync(); 4 } 5 6 7 public ReentrantLock(boolean fair) { 8 sync = (fair)? new FairSync() : new NonfairSync(); 9 }
在ReentrantLock中定義了2個靜態內部類,一個是NotFairSync,一個是FairSync,分別用來實現非公平鎖和公平鎖。
我們可以在建立ReentrantLock物件時,通過知道布林引數來決定使用 非公平鎖 還是公平鎖
如果引數為true表示為公平鎖,為fasle為非公平鎖。預設情況下,如果使用無參構造器,則是非公平鎖
另外在ReentrantLock類中定義了很多方法,比如:
isFair() //判斷鎖是否是公平鎖
isLocked() //判斷鎖是否被任何執行緒獲取了
isHeldByCurrentThread() //判斷鎖是否被當前執行緒獲取了
hasQueuedThreads() //判斷是否有執行緒在等待該鎖
在ReentrantReadWriteLock中也有類似的方法,同樣也可以設定為公平鎖和非公平鎖。
不過要記住,ReentrantReadWriteLock並未實現Lock介面,它實現的是ReadWriteLock介面。
4.讀寫鎖
讀寫鎖將對一個資源(比如檔案)的訪問分成了2個鎖,一個讀鎖和一個寫鎖。
正因為有了讀寫鎖,才使得多個執行緒之間的讀操作不會發生衝突。
ReadWriteLock就是讀寫鎖,它是一個介面,ReentrantReadWriteLock實現了這個介面。
可以通過readLock()獲取讀鎖,通過writeLock()獲取寫鎖。