讀寫鎖ReentrantReadWriteLock,使用它比ReentrantLock效率更高。java
讀寫鎖表示兩個鎖,一個是讀操做相關的鎖,稱爲共享鎖;另外一個是寫操做相關的鎖,稱爲排他鎖。安全
一、讀和讀之間不互斥,由於讀操做不會有線程安全問題線程
二、寫和寫之間互斥,避免一個寫操做影響另一個寫操做,引起線程安全問題code
三、讀和寫之間互斥,避免讀操做的時候寫操做修改了內容,引起線程安全問題get
多個Thread能夠同時進行讀取操做,可是同一時刻只容許一個Thread進行寫入操做。it
請看例子
ThreadDomain44類和main方法io
public class ThreadDomain44 extends ReentrantReadWriteLock { public void read() { try { readLock().lock(); System.out.println(Thread.currentThread().getName() + "得到了讀鎖, 時間爲" + System.currentTimeMillis()); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } finally { readLock().unlock(); } } public static void main(String[] args) { final ThreadDomain44 td = new ThreadDomain44(); Runnable readRunnable = new Runnable() { public void run() { td.read(); } }; Thread t0 = new Thread(readRunnable); Thread t1 = new Thread(readRunnable); t0.start(); t1.start(); } }
輸出結果以下class
Thread-0得到了讀鎖, 時間爲1564018325618 Thread-1得到了讀鎖, 時間爲1564018325618
儘管加了Thread.sleep(10000);兩個線程幾乎同時執行lock()後面的方法。說明readLock().lock()容許多個線程執行而且能提升執行效率。效率
請看例子方法
public class ThreadDomain45 extends ReentrantReadWriteLock { public void write() { try { writeLock().lock(); System.out.println(Thread.currentThread().getName() + "得到了寫鎖, 時間爲" + new Date()); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } finally { writeLock().unlock(); } } public static void main(String[] args) { final ThreadDomain45 td = new ThreadDomain45(); Runnable readRunnable = new Runnable() { public void run() { td.write(); } }; Thread t0 = new Thread(readRunnable); Thread t1 = new Thread(readRunnable); t0.start(); t1.start(); } }
輸出結果
Thread-1得到了寫鎖, 時間爲Tue Jul 30 11:26:21 CST 2019 Thread-0得到了寫鎖, 時間爲Tue Jul 30 11:26:31 CST 2019
能夠看到,後得到鎖的Thread-0等待了十秒,說明寫和寫互斥
例子以下
public class ThreadDomain46 extends ReentrantReadWriteLock { public void write() { try { writeLock().lock(); System.out.println(Thread.currentThread().getName() + "得到了寫鎖, 時間爲" + new Date()); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } finally { writeLock().unlock(); } } public void read() { try { readLock().lock(); System.out.println(Thread.currentThread().getName() + "得到了讀鎖, 時間爲" + new Date()); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } finally { readLock().unlock(); } } public static void main(String[] args) { final ThreadDomain46 td = new ThreadDomain46(); Runnable readRunnable = new Runnable() { public void run() { td.read(); } }; Runnable writeRunnable = new Runnable() { public void run() { td.write(); } }; Thread t0 = new Thread(readRunnable); Thread t1 = new Thread(writeRunnable); t0.start(); t1.start(); } }
輸出結果以下
Thread-0得到了讀鎖, 時間爲Tue Jul 30 11:49:15 CST 2019 Thread-1得到了寫鎖, 時間爲Tue Jul 30 11:49:26 CST 2019
能夠看到Thread-0得到讀鎖執行完10s後Thread-1纔得到了寫鎖,說明讀操做和寫操做互斥。
另外一種輸出結果以下
Thread-1得到了寫鎖, 時間爲Tue Jul 30 14:14:07 CST 2019 Thread-0得到了讀鎖, 時間爲Tue Jul 30 14:14:17 CST 2019
能夠看到Thread-1得到寫鎖執行完10s後Thread-0纔得到了讀鎖,說明寫操做和讀操做互斥。