JDK讀寫鎖ReadWriteLock的升級和降級問題
阿新 • • 發佈:2019-01-24
JDK提供了寫鎖介面ReadWriteLock和它的實現ReentrantReadWriteLock。要實現一個讀寫鎖,需要考慮很多細節,其中之一就是鎖升級和鎖降級的問題。什麼是升級和降級呢?ReadWriteLock的javadoc有一段話:
Can the write lock be downgraded to a read lock without allowing an intervening writer? Can a read lock be upgraded to a write lock,in preference to other waiting readers or writers?
鎖降級:從寫鎖變成讀鎖;鎖升級:從讀鎖變成寫鎖。讀鎖是可以被多執行緒共享的,寫鎖是單執行緒獨佔的。也就是說寫鎖的併發限制比讀鎖高,這可能就是升級/降級名稱的來源。
如下程式碼會產生死鎖,因為同一個執行緒中,在沒有釋放讀鎖的情況下,就去申請寫鎖,這屬於鎖升級,ReentrantReadWriteLock是不支援的。
ReadWriteLock rtLock = new ReentrantReadWriteLock(); rtLock.readLock().lock(); System.out.println("get readLock."); rtLock.writeLock().lock(); System.out.println("blocking");
ReentrantReadWriteLock支援鎖降級,如下程式碼不會產生死鎖。
ReadWriteLock rtLock = new ReentrantReadWriteLock();
rtLock.writeLock().lock();
System.out.println("writeLock");
rtLock.readLock().lock();
System.out.println("get read lock");
這段程式碼雖然不會導致死鎖,但沒有正確的釋放鎖。從寫鎖降級成讀鎖,並不會自動釋放當前執行緒獲取的寫鎖,仍然需要顯示的釋放,否則別的執行緒永遠也獲取不到寫鎖。鎖的釋放和獲取可以看下: 可重入鎖的獲取和釋放需要注意的一點兒事
final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Thread wt = new Thread(new Runnable()
{
@Override
public void run()
{
readWriteLock.writeLock().lock();
System.out.println("writeLock");
readWriteLock.readLock().lock();
System.out.println("readLock");
readWriteLock.readLock().unlock();
System.out.println("block");
}
});
wt.start();
Thread.sleep(100);
System.out.println("main blocking.");
readWriteLock.readLock().lock();