ReentrantReadWriteLock 可重入读写锁
功能概述:
并发处理过程中,避免不需要的锁等待,在数据不变的情况下,所有读取的线程不需要排队处理,可以同时进行。只有数据变更的操作跟其他操作是互斥的。
方法介绍
构造函数:指定公平还是非公平
- 读写两种锁,读操作使用读锁,写操作使用写锁。
- 每种锁都有其状态字段,等待队列和条件队列。
ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
WriteLock writeLock = reentrantReadWriteLock.writeLock();
writeLock.lock();
try {
...
}finally{
writeLock.unlock();
}
...
ReadLock readLock = reentrantReadWriteLock.readLock()
readLock.lock();
try{
...
}finally{
readLock.unlock();
}
排队规则
公平锁:
-
队列空:
1.1 R R 不排队(R:read,W :write)
1.2 RW ,WW,WR 排队 -
队列不为空:
2.1 RR 也排队
2.2 RW,WW ,WR排队 -
当前线程W 升 R可以(不用排队),R升W不可以
-
R被唤醒后,会唤醒后继的R,直到遇到W.在源码
setHeadAndPropagate
它会尝试去唤醒队列中下一个的处于Shared状态的节点。而下一个节点被唤醒时,会调用setHeadAndPropagate,来唤醒下一个Shared状态的节点。这样一直唤醒,直到遇见了一个独占状态的节点,这种连锁唤醒行动就停止了
非公平锁:
-
队列空:
1.1 R R 不排队
1.2 RW ,WW,WR 排队 -
队列不为空:
2.1 RR 不排队
2.2 RW,WW,WR 排队 -
线程内W 升 R可以(不用排队),R升W不可以
-
R被唤醒后,会唤醒后继的R,直到遇到W
Demo
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* https://blog.csdn.net/yanyan19880509/article/details/52435135
* 公平:
* 连续的读读不排队
* 读写,写读 ,写写 排队
*/
public class ReentrantReadWriteLockFairDemo {
static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(true);
static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
public static void main(String[] args) throws InterruptedException {
readAndWrite();
}
public static void readAndWrite() throws InterruptedException {
Thread readThread1 = new Thread(ReentrantReadWriteLockFairDemo::read,"read1");
Thread readThread2 = new Thread(ReentrantReadWriteLockFairDemo::read,"read2");
Thread readThread3 = new Thread(ReentrantReadWriteLockFairDemo::read,"read3");
Thread readThread4 = new Thread(ReentrantReadWriteLockFairDemo::read,"read4");
Thread writeThread1 = new Thread(ReentrantReadWriteLockFairDemo::write,"write1");
Thread writeThread2 = new Thread(ReentrantReadWriteLockFairDemo::write);
Thread writeThread3 = new Thread(ReentrantReadWriteLockFairDemo::write);
readThread1.start();
readThread2.start();
writeThread1.start();
TimeUnit.SECONDS.sleep(1);
readThread3.start();
readThread4.start();
writeThread2.start();
writeThread3.start();
readThread1.join();
readThread2.join();
readThread3.join();
readThread4.join();
writeThread1.join();
writeThread2.join();
writeThread3.join();
}
public static void read(){
readLock.lock();
try {
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getId() + " at: " + LocalDateTime.now() + " read");
} catch (InterruptedException e) {
e.printStackTrace();
}
//do something
}finally {
readLock.unlock();
}
}
public static void write(){
writeLock.lock();
try {
try {
TimeUnit.SECONDS.sleep(10);
System.out.println(Thread.currentThread().getId() + " at: " + LocalDateTime.now() + " write");
} catch (InterruptedException e) {
e.printStackTrace();
}
//do something
}finally {
writeLock.unlock();
}
}
}
网友评论