在第4步真正开始加锁,下面是该方法的源代码:

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();   //获取锁的开始,首先读volatile变量state
    if (c == 0) {
        if (isFirst(current) &&
            compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

  从上面源代码中我们可以看出,加锁方法首先读volatile变量state。

  在使用公平锁时,解锁方法unlock()的方法调用轨迹如下:

  1、ReentrantLock:unlock()

  2、AbstractQueuedSynchronizer:release(int arg)

  3、Sync:tryRelease(int releases)

  在第3步真正开始释放锁,下面是该方法的源代码:

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);           //释放锁的后,写volatile变量state
    return free;
}

  从上面的源代码我们可以看出,在释放锁的后写volatile变量state。

  公平锁在释放锁的后写volatile变量state;在获取锁时首先读这个volatile变量。根据volatile的happens-before规则,释放锁的线程在写volatile变量之前可见的共享变量,在获取锁的线程读取同一个volatile变量后将立即变的对获取锁的线程可见。

  现在我们分析非公平锁的内存语义的实现。

  非公平锁的释放和公平锁完全一样,所以这里仅仅分析非公平锁的获取。

  使用公平锁时,加锁方法lock()的方法调用轨迹如下:

  1、ReentrantLock:lock()

  2、NonfairSync:lock()

  3、AbstractQueuedSynchronizer:compareAndSetState(int expect, int update)

  在第3步真正开始加锁,下面是该方法的源代码:

protected final boolean compareAndSetState(int expect, int update) {
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}