美文网首页
ReentrantLock基于volatile state建立的

ReentrantLock基于volatile state建立的

作者: 王侦 | 来源:发表于2019-07-15 12:38 被阅读0次

    以非公平锁为例。

    1.加锁

        public void lock() {
            sync.lock();
        }
    
            final void lock() {
                if (compareAndSetState(0, 1))
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);
            }
    
        public final void acquire(int arg) {
            if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
                selfInterrupt();
        }
    

    其中tryAcquire(arg)调用的是NonfairSync的:

            protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
    

    nonfairTryAcquire(acquires)是其父类Sync中的final方法:

            final boolean nonfairTryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    if (compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;
                    if (nextc < 0) // overflow
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
    

    加锁总结如下:

    • 抢占锁使用CAS更新state;

    2.解锁

        public void unlock() {
            sync.release(1);
        }
    
        public final boolean release(int arg) {
            if (tryRelease(arg)) {
                Node h = head;
                if (h != null && h.waitStatus != 0)
                    unparkSuccessor(h);
                return true;
            }
            return false;
        }
    
            protected final boolean tryRelease(int releases) {
                int c = getState() - releases;
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
                boolean free = false;
                if (c == 0) {
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                setState(c);
                return free;
            }
    

    解锁总结:

    • 解锁首先会调用getState读取,然互殴调用 setState(c)更新

    3.volatile写-读内存语义

    • 当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存中。
    • 当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程直接从主存中读取共享变量

    当第二个操作是volatile写时,不允许重排序。确保了volatile写之前的操作不会重排序到volatile写之后。
    当第一个操作是volatile读时,不允许重排序。确保了volatile读之后的操作不会重排序到volatile读之前。

    volatile变量的happens-before规则:

    • 对于以volatile域的写,happens-before任意后续对于这个volatile域的读。

    总结上面的ReentrantLock的加锁和解锁:

    • 加锁使用CAS更新,相当于同时兼具了volatile的读和写
    • 解锁先读后写,也相当于同时兼具了volatile的读和写。

    因此在lock期间更新的共享内容对于另一个线程而言总是可见的。

    相关文章

      网友评论

          本文标题:ReentrantLock基于volatile state建立的

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