ReentrantReadWriteLock
文章目录
什么是读写锁
- ReentrantReadWriteLock
- 什么是读写锁
- 核心实现思想
- 计算演示
- 读写锁的特性
- 读写锁的组成
- 类图
- 构造函数
- 内部类Sync
- 构造方法
- 主要成员
- 主要方法
- Sync完整源码
- NonFairSync
- FairSync
- 写锁的获取与释放
- 读锁的获取与释放
- 锁的降级
读写锁支持支持多个线程同时读,但是当一个写线程访问的时候会阻塞其他所有写和读的线程。
读写锁同时拥有写锁和读锁,通过分离读写锁提高程序的执行效率,在读多写少的场景中,并发性能比单一的排他锁有明显提升。
核心实现思想读写锁内部重新定义了AQS中的同步状态变量的state。从低16位(0-15)用来记录写锁,用高16位(16-31)记录读锁。写锁的16位可以用来表示写锁被重入的次数。读锁的16位既可以表示一个读线程的重入次数,也可以表示多少个线程获得了读锁。state==0
表示既无写锁又无读锁。
// 共享式的位移量 读锁的使用的位数
static final int SHARED_SHIFT = 16;
// 将1左移16位,结果作为,高位读锁(共享)的计算基本单位 65536
static final int SHARED_UNIT = (1 16的值为1
exclusiveCount(5),通过以下计算得知:此时的读锁个数是5个。
------------------- -------------------
0000 0000 0000 0000 0000 0000 0000 0101 // 5的二进制
0000 0000 0000 0000 1111 1111 1111 1111 // EXCLUSIVE_MASK 65535
0000 0000 0000 0000 0000 0000 0000 0101 // 5 & 65535 = 5
读写锁的特性
特性说明公平性支持公平锁与非公平锁,默认非公平模式,吞吐量还是非公平高于公平重入性该锁支持重进入,以读写线程为例:读线程在获取了读锁之后,能够再次获取读锁。而写线程在获取写锁之后,能够再次获取写锁,同时可以获取读锁锁降级遵循读写锁、获取读锁在释放写锁的次序,写锁能够降级为读锁
读写锁的组成
类图
在构造函数中会去构造ReadLock和WriteLock,WriteLock和ReadLock使用的是同一个AQS对象(Sync),这样就具备AQS的特性且互斥。
/**
* 无参构造函数 默认采用非公平策略
*/
public ReentrantReadWriteLock() {
this(false);
}
/**
* 含参构造函数 false非公平策略 true公平策略
*/
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
// 读锁
public static class ReadLock implements Lock, java.io.Serializable {
private final Sync sync;
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
}
// 写锁
public static class WriteLock implements Lock, java.io.Serializable {
private final Sync sync;
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
}
内部类Sync
构造方法
主要是对读锁计数器的初始化。
Sync() {
// 初始化本地线程计数器
readHolds = new ThreadLocalHoldCounter();
setState(getState()); // ensures visibility of readHolds
}
// 利用ThreadLocal来存储本地线程计数器
static final class ThreadLocalHoldCounter
extends ThreadLocal {
public HoldCounter initialValue() {
return new HoldCounter();
}
}
// 本地线程计数器 count用来存储数量 tid代表线程的ID值
static final class HoldCounter {
int count = 0;
// Use id, not reference, to avoid garbage retention
final long tid = getThreadId(Thread.currentThread());
}
主要成员
// 共享式的位移量 读锁的使用的位数
static final int SHARED_SHIFT = 16;
// 将1左移16位,结果作为,高位读锁(共享)的计算基本单位
static final int SHARED_UNIT = (1
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?