读写锁ReentrantReadWriteLock,其核心就是实现读写分离的锁。在高并发访问下,尤其是读多写少的情况下,性能要远高于重入锁。
之前学synchronized、ReentrantLock时,我们知道,同一时间内,只能有一个线程进行访问被锁定的代码,那么读写锁则不同,其本质是分成两个锁,即读锁、写锁。在读锁下,多个线程可以并发的进行访问,但是在写锁的时候,只能一个一个的顺序访问。
•口诀:读读共享,写写互斥,读写互斥。【线程读的时候是并发访问,写的时候同ReentrantLock一样】
/* ReentrantReadWriteLock本质上就是ReentrantLock的升级,
* 提供两把锁ReadLock和WriteLock,实现读写分离思想;
* 其同样支持公平锁和非公平锁;
*/
public class UseReentrantReadWriteLock {
private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private ReadLock readLock = rwLock.readLock();
private WriteLock writeLock = rwLock.writeLock();
public void read() {
readLock.lock();
try {
System.out.println("当前线程:"+Thread.currentThread().getName()+"进入读方法...");
Thread.sleep(2000);
System.out.println("当前线程:"+Thread.currentThread().getName()+"退出读方法...");
} catch (Exception e) {
e.printStackTrace();
}finally {
readLock.unlock();
}
}
public void write() {
writeLock.lock();
try {
System.out.println("当前线程:"+Thread.currentThread().getName()+"进入写方法...");
Thread.sleep(2000);
System.out.println("当前线程:"+Thread.currentThread().getName()+"退出写方法...");
} catch (Exception e) {
e.printStackTrace();
}finally {
writeLock.unlock();
}
}
public static void main(String[] args) {
UseReentrantReadWriteLock rwLock = new UseReentrantReadWriteLock();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
rwLock.read();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
rwLock.read();
}
},"t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
rwLock.write();
}
},"t3");
t1.start();
t2.start();
t3.start();
}
}
当注释掉t3写线程,只启动t1和t2读线程时,输出结果:读读共享
当前线程:t2进入读方法...
当前线程:t1进入读方法...
当前线程:t2退出读方法...
当前线程:t1退出读方法...
全部运行(或1、3组合运行,2、3组合运行),输出结果:只有读写线程同时存在,那么就只能先运行一直在运行另一种
当前线程:t3进入写方法...
当前线程:t3退出写方法...
当前线程:t2进入读方法...
当前线程:t1进入读方法...
当前线程:t2退出读方法...
当前线程:t1退出读方法...