基于白嫖B站黑马程序员视频:全面深入学习java并发编程,java基础进阶中级必会教程
1 ReentrantReadWriteLock
支持可重入的读写锁,在于优化读写,读时间远远小于写,所以希望读-读并发。
1.1 使用例子
class Data {
private String data;//数据
private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();//读写锁
private ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();//获取读锁
private ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();//获取写锁
//读方法
public String read() {
readLock.lock();
try {
return this.data;
} finally {
readLock.unlock();
}
}
//写方法
public void write(String s) {
writeLock.lock();
try {
this.data = s;
} finally {
writeLock.unlock();
}
}
}
测试容易发现:读-读并发,读-写(写-读)互斥,写-写互斥;
1.2 注意点
- 读锁不支持条件变量condition;
- 重入不支持升级,即先获取读锁,想要获取写锁,不允许,会导致写锁永久等待;
- 重入支持降级,即先获得写锁,允许再获得读锁;
1.3 原理
- 使用的是同一个AQS同步器;
- 写锁占state低16位,读锁占state高16位;
- 一系列的读写逻辑;
2 StampedLock
jdk8加入的一种锁,优化读性能,要配合戳来使用;
StampedLock stampedLock = new StampedLock();//得到锁
long stamp = stampedLock.readLock();//获得读锁
stampedLock.unlockRead(stamp);//释放读锁
long stamp = stampedLock.writeLock();//获得写锁
stampedLock.unlockWrite(stamp);//释放写锁
注意新加内容:乐观读
stampedLock.tryOptimisticRead();//乐观读
主要用于优化读,加了戳校验,直接获取值,没有CAS操作,要是发现读之前和读之后,戳没有变,说明没有对值进行更改,可以使用,要是发生了更改,就锁升级,去读;
- 不支持条件变量;
- 不支部可重入;