有比 ReadWriteLock更快的锁?( 三 )


/*** 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 。
操作完成后,等待队列的结构如下:

有比 ReadWriteLock更快的锁?

文章插图
 
img
【有比 ReadWriteLock更快的锁?】注意:StampedLock中,等待队列的结点要比AQS中简单些,仅仅三种状态 。0:初始状态
-1:等待中
1:取消
另外,结点的定义中有个cowait字段,该字段指向一个栈,用于保存读线程,这个后续会讲到 。
// 节点状态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方法,加入等待队列:


推荐阅读