ReentrantReadWriteLock,读写锁,核心就是实现读写分离的锁,在高并发访问下,尤其是读多写少的场景下,性能要远远高于重入锁。之前的ReentrantLock和Synchronized在同一时间内只能有一个线程访问被锁定的代码,那么读写锁则不同,其本质时分成两个锁,读锁+写锁,在读锁下,多个线程可以并发地访问;但是在写锁的时候只能一个一个顺序访问。
总结:读读共享,读写互斥,写写互斥。
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; public class UseReentrantReadWriteLock { private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); private ReadLock readLock = rwLock.readLock(); private WriteLock writeLock = rwLock.writeLock(); public void read(){ try { readLock.lock(); System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..."); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + "退出..."); } catch (Exception e) { e.printStackTrace(); } finally { readLock.unlock(); } } public void write(){ try { writeLock.lock(); System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..."); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + "退出..."); } catch (Exception e) { e.printStackTrace(); } finally { writeLock.unlock(); } } public static void main(String[] args) { final UseReentrantReadWriteLock urrw = new UseReentrantReadWriteLock(); Thread t1 = new Thread(new Runnable() { @Override public void run() { urrw.read(); } }, "t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { urrw.read(); } }, "t2"); Thread t3 = new Thread(new Runnable() { @Override public void run() { urrw.write(); } }, "t3"); Thread t4 = new Thread(new Runnable() { @Override public void run() { urrw.write(); } }, "t4"); //读读共享 // t1.start();//R // t2.start();//R //读写互斥 // t1.start(); // R // t3.start(); // W //写写互斥 t3.start();//W t4.start();//W } }
分析:在两个线程一起访问的是一个被读锁锁定的方法时,可以一起进入读取数据,相当于数据是共享的。但是如果一个访问的是读锁锁定的方法,一个访问的是写锁锁定的方法,则相当于访问的是同一把锁,只能等一个访问完释放后,另外一个线程才能继续访问,写写亦然。