/*** Creates a new lock, initially in unlocked state.*/public StampedLock() { state = ORIGIN;}
另外,StamedLock提供了三类视图:
// viewstransient ReadLockView readLockView;transient WriteLockView writeLockView;transient ReadWriteLockView readWriteLockView;
这些视图其实是对StampedLock方法的封装,便于习惯了ReentrantReadWriteLock的用户使用:例如,ReadLockView其实相当于ReentrantReadWriteLock.readLock()返回的读锁;
final class ReadLockView implements Lock { public void lock() { readLock(); } public void lockInterruptibly() throws InterruptedException { readLockInterruptibly(); } public boolean tryLock() { return tryReadLock() != 0L; } public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return tryReadLock(time, unit) != 0L; } public void unlock() { unstampedUnlockRead(); } public Condition newCondition() { throw new UnsupportedOperationException(); }}
2. ThreadA调用writeLock获取写锁来看下writeLock方法:
/** * 获取写锁,如果获取失败则进入阻塞 * 注意该方法不响应中断 * * @return 返回一个非0的值表示成功,用于解锁或者转换锁模式 */public long writeLock() { long s, next; return ((((s = state) & ABITS) == 0L && // ((s = state) & ABITS) == 0L表示读锁和写锁都未被使用 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ? // CAS将第8位置为1,表示写锁被占用 next : acquireWrite(false, 0L)); // 获取失败则调用acquireWrite,加入等待队列}
StampedLock中大量运用了位运算,这里(s = state) & ABITS == 0L 表示读锁和写锁都未被使用,这里写锁可以立即获取成功,然后CAS操作更新同步状态值State 。
操作完成后,等待队列的结构如下:
文章插图
img
【有比 ReadWriteLock更快的锁?】注意:StampedLock中,等待队列的结点要比AQS中简单些,仅仅三种状态 。0:初始状态另外,结点的定义中有个cowait字段,该字段指向一个栈,用于保存读线程,这个后续会讲到 。
-1:等待中
1:取消
// 节点状态private static final int WAITING = -1;private static final int CANCELLED = 1;// 节点类型private static final int RMODE = 0;private static final int WMODE = 1;/** * 等待队列的节点定义 */static final class WNode { volatile WNode prev; volatile WNode next; volatile WNode cowait; // 该模式使用该节点形成栈 volatile Thread thread; // non-null while possibly parked volatile int status; // 0, WAITING, or CANCELLED final int mode; // RMODE or WMODE WNode(int m, WNode p) { mode = m; prev = p; } }/** 等待队列头结点指针 */private transient volatile WNode whead;/** 等待队列尾结点指针 */private transient volatile WNode wtail;
3. ThreadB调用readLock获取读锁来看下readLock方法:由于ThreadA此时持有写锁,所以ThreadB获取读锁失败,将调用acquireRead方法,加入等待队列:
推荐阅读
- 好壶难得知己更难求,茶具知识什么是花器
- 比宇宙更古老的恒星 宇宙最古老的恒星
- 漂亮的女人离婚概率更大是为什么?
- 经常喝茶好吗,如何品茶会更健康
- 据说“新陈代谢”快的人更健康!用运动来为代谢“加速”
- 冬天严寒手脚干裂 护手霜使用不当副作用更大
- 冬季泡脚要加四样宝 养生效果会更好
- Android端微软远程桌面应用更新:全面支持Windows虚拟桌面
- 饮食|更适合老年人的饮食结构是什么?
- 失眠吃什么好 治疗更年期失眠的六款药膳粥