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
-
}
-
}
分析:在两个线程一起访问的是一个被读锁锁定的方法时,可以一起进入读取数据,相当于数据是共享的。但是如果一个访问的是读锁锁定的方法,一个访问的是写锁锁定的方法,则相当于访问的是同一把锁,只能等一个访问完释放后,另外一个线程才能继续访问,写写亦然。