DK1.5以後,提供了讀寫鎖ReentrantReadWriteLock,讀寫鎖維護了一對鎖:一個讀鎖,一個寫鎖。經過分離讀鎖和寫鎖,使得併發性相比通常的排他鎖有了很大提高。在讀多寫少的狀況下,讀寫鎖可以提供比排他鎖更好的併發性和吞吐量。java
/* * <p>This lock supports a maximum of 65535 recursive write locks * and 65535 read locks. Attempts to exceed these limits result in * {@link Error} throws from locking methods. * * @since 1.5 * @author Doug Lea */ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable { private static final long serialVersionUID = -6992448646407690164L; /** Inner class providing readlock */ private final ReentrantReadWriteLock.ReadLock readerLock; /** Inner class providing writelock */ private final ReentrantReadWriteLock.WriteLock writerLock; /** Performs all synchronization mechanics */ final Sync sync; ... }
public class ReentrantReadWriteLockTest { ReentrantReadWriteLock lock; private ReentrantReadWriteLock.ReadLock readLock; private ReentrantReadWriteLock.WriteLock writeLock; private ReentrantReadWriteLockTest() { lock = new ReentrantReadWriteLock(); readLock = lock.readLock(); writeLock = lock.writeLock(); } public void read() { try { readLock.lock(); System.out.println(Thread.currentThread().getName() + " 開始讀了。。。"); Thread.sleep(3000); }catch (InterruptedException e) { }finally { System.out.println(Thread.currentThread().getName() + " 讀結束了。。。"); readLock.unlock(); } } public void write() { try { writeLock.lock(); System.out.println(Thread.currentThread().getName() + " 開始寫了。。。"); Thread.sleep(3000); } catch (InterruptedException e) { } finally { System.out.println(Thread.currentThread().getName() + " 寫完了。。。"); writeLock.unlock(); }
} }
測試1併發
public static void main(String[] args) { final ReentrantReadWriteLockTest test = new ReentrantReadWriteLockTest(); Thread t1 = new Thread(new Runnable() { @Override public void run() { test.read(); } }, "ReadThread1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { test.read(); } }, "ReadThread2"); Thread t3 = new Thread(new Runnable() { @Override public void run() { test.write(); } }, "WriteThread1"); Thread t4 = new Thread(new Runnable() { @Override public void run() { test.write(); } }, "WriteThread4"); t1.start(); t2.start(); }
輸出ide
ReadThread1 開始讀了。。。 ReadThread2 開始讀了。。。 ReadThread1 讀結束了。。。 ReadThread2 讀結束了。。。
結論:讀讀共享 測試
測試2spa
t2.start();
t3.start();
輸出code
ReadThread2 開始讀了。。。 ReadThread2 讀結束了。。。 WriteThread1 開始寫了。。。 WriteThread1 寫完了。。。
結論:讀寫互斥orm
測試3blog
t4.start();
t3.start();
輸出get
WriteThread4 開始寫了。。。 WriteThread4 寫完了。。。 WriteThread1 開始寫了。。。 WriteThread1 寫完了。。。
結論:寫寫互斥源碼
注意:新生成變量時,要用final修飾
final ReentrantReadWriteLockTest test = new ReentrantReadWriteLockTest();
緣由:從內部類訪問本地變量,本地變量要被聲明爲final類型