读写锁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才得到了读锁,说明写操做和读操做互斥。