深入理解读写锁ReentrantReadWriteLock
1.读写锁的介绍
在并发场景中用于解决线程安全的问题,我们几乎会提供高频率的使用到独占式锁,通常使用java提供的关键字synchronized(关于synchronized可以看这篇文章)或者concurrents包中实现了Lock接口的ReetrantLock.它们都是独占式获取锁,也就是在同一时刻只有一个线程能够获取锁.而在一些业务场景中,大部分数据只是读数据,写数据少,如果仅仅是读数据的话并不会影响数据正确性(出现脏读),而如果在这种业务情况下,依然使用独占锁的话,很显然这将是出现性能瓶颈的地方.针对这种读多写少的情况,java还提供了另外一个实现Lock接口的ReentrantReadWriteLock(读写锁).读写锁允许同一时刻被多个读线程访问,但是在写线程访问时,所有的读线程和其他的写线程都会被阻塞.在分析WirteLock和ReadLock的互斥性时可以按照WriteLock与WriteLock之间,WriteLock与ReadLock之间以及ReadLock与ReadLock之间进行分析。更多关于读写锁特性介绍大家可以看源码上的介绍(阅读源码时最好的一种学习方式,我也正在学习中,与大家共勉),这里做一个归纳总结:
- 公平锁选择:支持非公平性(默认)和公平的锁获取方式,吞吐量还是非公平性由于公平;
- 重入性:支持重入,读锁获取后能再次获取,写锁获取以后能够再次获取锁,同时也能够获取读锁;
- 锁降级:遵循获取写锁,获取读锁再释放写锁的次序,写锁能够降级成为读锁;
要想能够彻底的理解读写锁必须能够理解这样几个问题:
- 读写锁是怎样实现分别记录读写状态的?
- 写锁是怎样获取和释放的?
- 读锁是怎样获取和释放的?