Java读写锁(ReentrantReadWriteLock )学习笔记
读写锁底层实现
state是一个32位的int值,使用高16位表示读锁,低16位表示写锁。
读锁:有读锁已经锁定的情况下,其他读锁可以继续加锁,写锁阻塞。
写锁:写锁持有时,其他读锁和写锁都阻塞。
使用场景
读多写少的情况,比如cache系统。
经典问题
什么是读写锁的锁降级?
锁降级是指在一个线程已经获取了写锁的情况下,再获取读锁,然后释放写锁的过程。在Java的ReentrantReadWriteLock中,如果当前线程已经拥有写锁,它可以继续获取读锁而不被阻塞。然而,只有当释放写锁后再获取读锁时,才称为真正的锁降级
读写锁的锁降级是用来解决什么问题的?
在实际应用中,锁降级常用于需要先写后读的场景。例如,一个线程首先获取写锁进行数据修改,然后通过锁降级获取读锁,以便其他线程可以安全地读取数据。这样可以避免在单线程下由于先写后读导致的读写不一致问题
锁降级可解决单线程下写读不一致的问题。比如该单线程先获取写锁写入i=1; 释放写锁后,再来读取该变量i,可能变量此时已经变成了i=2;(在线程释放写锁获取读锁前,该变量被其他线程获得了写锁并修改为2)
使用案例代码
public class CachedData {
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private Object data;
private boolean cacheValid;
public void processCachedData() {
// Acquire read lock
rwl.readLock().lock();
if (!cacheValid) {
// Must release read lock before acquiring write lock
rwl.readLock().unlock();
rwl.writeLock().lock();
try {
// Recheck state because another thread might have
// acquired write lock and changed state before we did
if (!cacheValid) {
data = fetchDataFromDatabase();
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
rwl.readLock().lock();
} finally {
rwl.writeLock().unlock(); // Unlock write, still hold read
}
}
try {
use(data);
} finally {
rwl.readLock().unlock();
}
}
private Object fetchDataFromDatabase() {
// Simulate fetching data from a database
return new Object();
}
private void use(Object data) {
// Simulate using the data
System.out.println("使用数据: " + data);
}
public static void main(String[] args) {
CachedData cachedData = new CachedData();
cachedData.processCachedData();
}
}
学习资料:
深入理解Java并发读写锁ReentrantReadWriteLock | 二哥的Java进阶之路
谈谈Java的读写锁-锁降级和锁升级_java 读写锁 锁升降级-CSDN博客