本文基於ReentrantReadWriteLock來說明它自己的鎖升級的策略。
讀寫鎖總結
這里我先說明下讀寫鎖進行下總結:
要么多讀,要么一寫;讀寫鎖適用去讀多寫鎖的情況。
公平情況下,讀寫鎖都不能插隊;非公平情況下,寫鎖可以插隊,讀鎖只有在頭結點不是寫等待的情況下插隊。
讀鎖是否可以升級到寫鎖
這里我先給出結論:讀鎖不可以升級為寫鎖;若兩個線程的讀鎖都想升級寫鎖,則需要對方都釋放自己鎖,而雙方都不釋放,就會產生死鎖。
實現代碼如下所示
package com.yang.lock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * 本實例演示讀鎖的升級 */ public class ReentrantReadWriteUpgardeDemo { private static ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock(false); private static ReentrantReadWriteLock.ReadLock readLock=reentrantReadWriteLock.readLock(); private static ReentrantReadWriteLock.WriteLock writeLock=reentrantReadWriteLock.writeLock(); public void upgarde(){ System.out.println(Thread.currentThread().getName()+"嘗試獲取讀鎖"); readLock.lock(); try{ System.out.println(Thread.currentThread().getName()+"獲取到了讀鎖"); System.out.println(Thread.currentThread().getName()+"阻塞獲取寫鎖"); writeLock.lock(); }finally { readLock.unlock(); } } public static void main(String[] args) { ReentrantReadWriteUpgardeDemo reentrantReadWriteUpgardeDemo=new ReentrantReadWriteUpgardeDemo(); new Thread(()->reentrantReadWriteUpgardeDemo.upgarde(),"線程1").start(); new Thread(()->reentrantReadWriteUpgardeDemo.upgarde(),"線程2").start(); } }
寫鎖是否可以降級為讀鎖
這里我先給出結論:寫鎖是可以降級為讀鎖的;寫鎖只有一個,當寫鎖降級為讀鎖時,所有的都是讀。
實現代碼如下所示
package com.yang.lock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * 本實例演示讀鎖的升級 */ public class ReentrantReadWriteDowngradeDemo { private static ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock(false); private static ReentrantReadWriteLock.ReadLock readLock=reentrantReadWriteLock.readLock(); private static ReentrantReadWriteLock.WriteLock writeLock=reentrantReadWriteLock.writeLock(); public void downgrade(){ System.out.println(Thread.currentThread().getName()+"嘗試獲取寫鎖"); writeLock.lock(); try{ System.out.println(Thread.currentThread().getName()+"獲取到了寫鎖"); System.out.println(Thread.currentThread().getName()+"降級獲取讀鎖"); readLock.lock(); try{ }finally { readLock.unlock(); } }finally { writeLock.unlock(); } } public static void main(String[] args) { ReentrantReadWriteDowngradeDemo reentrantReadWriteUpgardeDemo=new ReentrantReadWriteDowngradeDemo(); new Thread(()->reentrantReadWriteUpgardeDemo.downgrade(),"線程1").start(); new Thread(()->reentrantReadWriteUpgardeDemo.downgrade(),"線程2").start(); } }
運行結果如下圖所示: