ReentrantReadWriteLock样例
public class ReadWriteLockTest {
public DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss:SSS");
public ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public String getTime(){
return LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
//字符串转时间String dateTimeStr = "2018-07-28 14:11:15";
}
public void readLockTest(){
try {
readWriteLock.readLock().lock();
System.out.println("start readLockTest at "+getTime());
Thread.sleep(2000);
System.err.println("end readLockTest at "+getTime());
}catch (InterruptedException e){
e.printStackTrace();
}finally {
readWriteLock.readLock().unlock();
}
}
public void writeLockTest(){
try {
readWriteLock.writeLock().lock();
System.out.println("start writeLockTest at "+getTime());
Thread.sleep(2000);
System.err.println("end writeLockTest at "+getTime());
}catch (InterruptedException e){
e.printStackTrace();
}finally {
readWriteLock.writeLock().unlock();
}
}
public static void main(String[] args) {
/*
a << b就表示把a转为二进制后左移b位(在后面添b个0)。
a >> b表示二进制右移b位(去掉末b位).
*/
ReadWriteLockTest readWriteLockTest = new ReadWriteLockTest();
IntStream.range(0,4).forEach(i-> new Thread(readWriteLockTest::readLockTest).start());
IntStream.range(0,4).forEach(i-> new Thread(readWriteLockTest::writeLockTest).start());
}
}
复制代码
不厌其烦的阅读jdk源码
ReadWriteLock接口
其中一个实现类ReentrantReadWriteLock
构造方法和成员变量
WriteLock的构造类似,不再赘述
AQS在ReentrantReadWriteLock中的角色
ReentrantReadWriteLock的ReadLock获取锁的源码分析
ReentrantReadWriteLock的WriteLock获取锁的源码分析
Sync有两个版本
***ShouldBlock()
,在获取锁的tryAcquire()
方法中有调用
小结——关于ReentrantReadWriteLock获取锁的操作逻辑:
- 读锁:
- 在获取读锁时,会尝试判断当前对象是否拥有了写锁,如果已经拥有,则直接获取失败。
- 如果没有写锁,就表示当前对象没有排他锁(写锁),则当前线程会尝试给对象加锁。
- 如果当前线程已经持有了该对象的锁,那么直接将读锁数量加1(可重入)。
- 写锁:
- 在获取写锁时,会尝试判断当前对象是否拥有了锁(读锁与写锁),只能选其一。如果已经拥有且持有锁的线程并非当前线程,直接获取失败。
- 如果当前对象没有被加锁,那么写锁就会为当前对象上锁,并且将写锁的个数加1(可重入)。
- 将当前对象的排他锁线程持有者设为自己(
setExclusiveOwnerThread(current)
);
近期评论