美文网首页
StampedLock错误用法:非中断锁线程调用interrup

StampedLock错误用法:非中断锁线程调用interrup

作者: 王侦 | 来源:发表于2019-07-27 14:41 被阅读0次

    1.错误用法:在调用readLock()线程中进行中断

    import java.util.concurrent.locks.LockSupport;
    import java.util.concurrent.locks.StampedLock;
    
    public class TestStampedLock {
        public static void main(String[] args) throws InterruptedException {
            final StampedLock lock = new StampedLock();
            new Thread() {
                public void run() {
                    long readLong = lock.writeLock();
                    LockSupport.parkNanos(6100000000L);
                    lock.unlockWrite(readLong);
                }
            }.start();
            Thread.sleep(100);
            for (int i = 0; i < 3; ++i)
                new Thread(new OccupiedCPUReadThread(lock)).start();
        }
    
        private static class OccupiedCPUReadThread implements Runnable {
            private StampedLock lock;
    
            public OccupiedCPUReadThread(StampedLock lock) {
                this.lock = lock;
            }
    
            public void run() {
                Thread.currentThread().interrupt();
                long lockr = lock.readLock();
                System.out.println(Thread.currentThread().getName() + " get read lock");
                lock.unlockRead(lockr);
            }
        }
    }
    

    根据interrupt()中断行为研究可知,由于线程设置了中断标志,因此readLock() -> acquireRead(false, 0L)中的U.park(false, time)无法阻塞,会导致线程不断死循环(CPU爆满)。

        public long readLock() {
            long s = state, next;  // bypass acquireRead on common uncontended case
            return ((whead == wtail && (s & ABITS) < RFULL &&
                     U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
                    next : acquireRead(false, 0L));
        }
    
        private long acquireRead(boolean interruptible, long deadline) {
            WNode node = null, p;
            for (int spins = -1;;) {
                WNode h;
                if ((h = whead) == (p = wtail)) {
                    for (long m, s, ns;;) {
                        if ((m = (s = state) & ABITS) < RFULL ?
                            U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
                            (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L))
                            return ns;
                        else if (m >= WBIT) {
                            if (spins > 0) {
                                if (LockSupport.nextSecondarySeed() >= 0)
                                    --spins;
                            }
                            else {
                                if (spins == 0) {
                                    WNode nh = whead, np = wtail;
                                    if ((nh == h && np == p) || (h = nh) != (p = np))
                                        break;
                                }
                                spins = SPINS;
                            }
                        }
                    }
                }
                if (p == null) { // initialize queue
                    WNode hd = new WNode(WMODE, null);
                    if (U.compareAndSwapObject(this, WHEAD, null, hd))
                        wtail = hd;
                }
                else if (node == null)
                    node = new WNode(RMODE, p);
                else if (h == p || p.mode != RMODE) {
                    if (node.prev != p)
                        node.prev = p;
                    else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
                        p.next = node;
                        break;
                    }
                }
                else if (!U.compareAndSwapObject(p, WCOWAIT,
                                                 node.cowait = p.cowait, node))
                    node.cowait = null;
                else {
                    for (;;) {
                        WNode pp, c; Thread w;
                        if ((h = whead) != null && (c = h.cowait) != null &&
                            U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
                            (w = c.thread) != null) // help release
                            U.unpark(w);
                        if (h == (pp = p.prev) || h == p || pp == null) {
                            long m, s, ns;
                            do {
                                if ((m = (s = state) & ABITS) < RFULL ?
                                    U.compareAndSwapLong(this, STATE, s,
                                                         ns = s + RUNIT) :
                                    (m < WBIT &&
                                     (ns = tryIncReaderOverflow(s)) != 0L))
                                    return ns;
                            } while (m < WBIT);
                        }
                        if (whead == h && p.prev == pp) {
                            long time;
                            if (pp == null || h == p || p.status > 0) {
                                node = null; // throw away
                                break;
                            }
                            if (deadline == 0L)
                                time = 0L;
                            else if ((time = deadline - System.nanoTime()) <= 0L)
                                return cancelWaiter(node, p, false);
                            Thread wt = Thread.currentThread();
                            U.putObject(wt, PARKBLOCKER, this);
                            node.thread = wt;
                            if ((h != pp || (state & ABITS) == WBIT) &&
                                whead == h && p.prev == pp)
                                U.park(false, time);
                            node.thread = null;
                            U.putObject(wt, PARKBLOCKER, null);
                            if (interruptible && Thread.interrupted())
                                return cancelWaiter(node, p, true);
                        }
                    }
                }
            }
    
            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 m, s, ns;
                        if ((m = (s = state) & ABITS) < RFULL ?
                            U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
                            (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
                            WNode c; Thread w;
                            whead = node;
                            node.prev = null;
                            while ((c = node.cowait) != null) {
                                if (U.compareAndSwapObject(node, WCOWAIT,
                                                           c, c.cowait) &&
                                    (w = c.thread) != null)
                                    U.unpark(w);
                            }
                            return ns;
                        }
                        else if (m >= WBIT &&
                                 LockSupport.nextSecondarySeed() >= 0 && --k <= 0)
                            break;
                    }
                }
                else if (h != null) {
                    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;
                        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) == WBIT) &&
                            whead == h && node.prev == p)
                            U.park(false, time);
                        node.thread = null;
                        U.putObject(wt, PARKBLOCKER, null);
                        if (interruptible && Thread.interrupted())
                            return cancelWaiter(node, node, true);
                    }
                }
            }
        }
    

    2.中断情况应该使用readLockInterruptibly()

        public long readLockInterruptibly() throws InterruptedException {
            long next;
            if (!Thread.interrupted() &&
                (next = acquireRead(true, 0L)) != INTERRUPTED)
                return next;
            throw new InterruptedException();
        }
    

    相关文章

      网友评论

          本文标题:StampedLock错误用法:非中断锁线程调用interrup

          本文链接:https://www.haomeiwen.com/subject/ppghrctx.html