美文网首页
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