Java中的读写锁ReentrantReadWriteLock
请说明ReentrantReadWriteLock的读写分离原理,以及可能出现写饥饿问题及解决方案。
回答
我还是少年
ReentrantReadWriteLock:
- 维护一对锁:读锁(共享锁)和写锁(排他锁)。
- 读写分离:读读不互斥,读写互斥,写写互斥。
- state高16位表示读锁计数,低16位表示写锁计数(写锁可重入)。
写饥饿问题:
- 当读锁被大量线程持有时,写锁永远无法获取(因为读写互斥)。
- 读锁释放前写线程一直阻塞,可能导致写线程长时间等待甚至超时。
解决方案:
- 公平模式:ReentrantReadWriteLock(true),按照FIFO顺序获取锁,写锁排队在前时后续读锁不会插队。
- StampedLock:乐观读不阻塞写,写线程可打断乐观读。
- 读写锁降级:写锁→读锁(写线程获取写锁后可以降级为读锁再释放写锁,避免其他写线程插入)。
- 限流读操作:控制同时读的线程数。
注意:读锁不能升级为写锁(会导致死锁),但写锁可以降级为读锁。