什么是读写锁
根据名字我们也可以猜个大概,就是有两把锁,分别是读锁和写锁。读锁在同一时刻可以允许多个读线程获取,但是在写线程访问的时候,所有的读线程和其他写线程都会被阻塞。写锁同一时刻只能有一个写线程获取成功,其他都会被阻塞。读写锁实际维护了两把锁,一个读锁和一个写锁,通过读锁和写锁进行区分,在读多写少的情况下并发性比独占锁有了很大的提升。在java里面对读写锁的实现就是ReentrantReadWriteLock,它有以下特性:
- 公平性选择:支持非公平性(默认)和公平的锁获取方式,吞吐量还是非公平优于公平;
- 重入性:支持重入,读锁获取后能再次获取,写锁获取之后能够再次获取写锁,同时也能够获取读锁;
- 锁降级:遵循获取写锁,获取读锁再释放写锁的次序,写锁能够降级成为读锁
-
这个使用起来还是非常简单明了的,跟ReentrantLock的用法基本一致,写的时候获取写锁,写完了释放写锁,读的时候获取读锁,读完了就释放读写。
读写锁的实现分析
我们知道ReentrantLock是通过state来控制锁的状态,以及前面所介绍的《Java高并发编程基础三大利器之Semaphore》《Java高并发编程基础三大利器之CountDownLatch》《Java高并发编程基础三大利器之CyclicBarrier》 都是通过state来进行实现的那ReentrantReadWriteLock毋庸置疑肯定也是通过AQS的state来实现的,不过state是一个int值它是如何来读锁和写锁的。
读写锁状态的实现分析
如果我们有看过线程池的源码,我们知道线程池的状态和线程数是通过一个int类型原子变量(高3位保存运行状态,低29位保存线程数)来控制的。同样的ReentrantReadWriteLock也是通过一个state的高16位和低16位来分别控制读的状态和写状态。