以下是StampedLock中相关掩码示意图。从掩码的使用角度来解析StampedLock的实现原理
掩码注释
首先对上图的掩码关键字进行简单解释,再介绍乐观锁悲观锁的实现逻辑
WBIT:写锁的掩码位,只包含1位
RBITS:读锁7位掩码
SBITS:乐观锁版本号57位(含WBIT)
悲观锁实现原理
悲观锁主要基于低8位ABITS(WBIT | RBITS)进行实现。
acquire写锁,判断state&ABITS 是否等于0,如果等于0通过CAS将WBIT置为1从而获得写锁;
acquire读锁,判断state&ABITS是否等于WBIT,相等时说明已经被写锁获取,获取读锁失败。不相等说明没被获取,直接捕获读锁(CAS state+1)
乐观锁实现原理
乐观锁通过高位57位作为版本号来控制。
首先获取乐观锁需要WBIT为0(state & WBIT == 0) 说明,未被写锁占用,可获得版本号(state&SBITS) ,否者返回0,后面做版本号校验失踪失败(调用validate(stamp)失败)
关键操作写锁释放操作为state+WBIT, 通过这个操作WBIT位变为0表示写锁释放,同时乐观锁版本号(高57位)获得变化(+1),导致之前获得的乐观锁版本号stamp在validate(stamp)验证时失败
相关问题解答
1)为什么写锁不可重入?
因为WBIT只有1位只能做0和1判断,没有用于表示重入次数的count变量
2)锁的释放对线程有依赖吗?
没有,只要stamp符合要求(如一个线程获得写锁返回的stamp),就可正常释放对应的锁。StampLock中并没有像AQS中的互斥线程的变量。