1. 程式人生 > >JDK讀寫鎖ReadWriteLock的升級和降級問題

JDK讀寫鎖ReadWriteLock的升級和降級問題

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();