StampedLock

最近看并发工具类的遇到这个玩意,据说效率比ReentrantLock高,咱也没用过,闲得慌,源码先扒了再说,不定期更新。

锁状态变量

既然是相似读写锁,必定也有变量用于记录锁状态,绝对于读写锁应用Int,StampedLock中使Long类型(64位)示意锁状态,其中第8位示意写锁持有状态,低7位用于示意持有读锁的线程数。(目前还未搞懂为啥用Long,待前面钻研)

    private static final long RUNIT = 1L; //读锁线程减少时,    //获取写锁状态的掩码:1000 000    private static final long WBIT  = 1L << LG_READERS;     //获取读锁状态的掩码:0111 1111    private static final long RBITS = WBIT - 1L;    //读锁持有数量的下限    private static final long RFULL = RBITS - 1L;    //获取锁的状态,用于判断是否有线程持有读锁或写锁    private static final long ABITS = RBITS | WBIT;    //RBITS 取反,作用未钻研    private static final long SBITS = ~RBITS; // note overlap with ABITS

写锁获取

    public long writeLock() {        long s, next;         //如果没有任何线程持有锁,CAS尝试增加写锁状态        //如果失败,则acquireWrite办法中自旋尝试获锁,再次失败入队        return ((((s = state) & ABITS) == 0L &&                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?                next : acquireWrite(false, 0L));    }

acquireWrite办法巨长,真难看

 private long acquireWrite(boolean interruptible, long deadline) {        WNode node = null, p;        for (int spins = -1;;) { // spin while enqueuing            long m, s, ns;            // 再次尝试获取写锁,胜利则返回以后的锁状态            if ((m = (s = state) & ABITS) == 0L) {                if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))                    return ns;            }            else if (spins < 0)                 //写锁被其它线程占有,且期待队列为空(头等于尾)时,不批改spins                 spins = (m == WBIT && wtail == whead) ? SPINS : 0;            else if (spins > 0) {                // 产生一个随机数,判断是否大于0                if (LockSupport.nextSecondarySeed() >= 0)                    --spins;            }            else if ((p = wtail) == null) { // 初始化期待队列                WNode hd = new WNode(WMODE, null);                if (U.compareAndSwapObject(this, WHEAD, null, hd))                    wtail = hd;            }            //上面三个if就是将node采纳尾插法插入期待队列            else if (node == null)                node = new WNode(WMODE, p);            else if (node.prev != p)                node.prev = p;            else if (U.compareAndSwapObject(this, WTAIL, p, node)) {                p.next = node;                break;            }        }        for (int spins = -1;;) {            WNode h, np, pp; int ps;            if ((h = whead) == p) {                if (spins < 0)                    spins = HEAD_SPINS;                else if (spins < MAX_HEAD_SPINS)                    spins <<= 1;                for (int k = spins;;) { // spin at head                    long s, ns;                    if (((s = state) & ABITS) == 0L) {                        if (U.compareAndSwapLong(this, STATE, s,                                                 ns = s + WBIT)) {                            whead = node;                            node.prev = null;                            return ns;                        }                    }                    else if (LockSupport.nextSecondarySeed() >= 0 &&                             --k <= 0)                        break;                }            }            else if (h != null) { // help release stale waiters                WNode c; Thread w;                while ((c = h.cowait) != null) {                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&                        (w = c.thread) != null)                        U.unpark(w);                }            }            if (whead == h) {                if ((np = node.prev) != p) {                    if (np != null)                        (p = np).next = node;   // stale                }                else if ((ps = p.status) == 0)                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);                else if (ps == CANCELLED) {                    if ((pp = p.prev) != null) {                        node.prev = pp;                        pp.next = node;                    }                }                else {                    long time; // 0 argument to park means no timeout                    if (deadline == 0L)                        time = 0L;                    else if ((time = deadline - System.nanoTime()) <= 0L)                        return cancelWaiter(node, node, false);                    Thread wt = Thread.currentThread();                    U.putObject(wt, PARKBLOCKER, this);                    node.thread = wt;                    if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&                        whead == h && node.prev == p)                        U.park(false, time);  // emulate LockSupport.park                    node.thread = null;                    U.putObject(wt, PARKBLOCKER, null);                    if (interruptible && Thread.interrupted())                        return cancelWaiter(node, node, true);                }            }        }    }