ReentrantLock原理2-重入原理

  • Post author:
  • Post category:其他


以非公平锁为例

  • ReentrantLock的lock调用了其内部类(AQS)的lock方法
    public void lock() {
        sync.lock();
    }
  • 看非公平锁实现此接口
abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * Performs {@link Lock#lock}. The main reason for subclassing
         * is to allow fast path for nonfair version.
         */
        abstract void lock();
    ***省略**
}
  • 如果是第一次就让state原子性加1,并把当前线程设置为owner线程,表示第一次来竞争成功,否则调用acquire方法
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }
    }
  • acquire逻辑还会尝试竞争锁,失败会将线程加入队列,尝试竞争资源逻辑是tryAcquire
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
  • 这个是AQS的定义的默认方法,现在就要看ReetrantLock中内部类重写次方法的逻辑
    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }
  • 当我们进入此逻辑时,还会去判断state是否为0,如果为0,就表示首次获得锁(因为进入此逻辑时,原来占有的资源的线程可能会释放),进行的逻辑和之前的逻辑相同。如果已经获得锁,看当前线程是否等于owner线程,表示发生了锁重入,发生锁重入,将state++,返回true。

  • tryRelease

    ,当进入此方法时,判断当前线程是否等于getExclusiveOwnerThread的线程,如果相同,则会让state–,让后false,并不会去唤醒其他线程,因为重入状态并不会真正是否锁,当检测到state为0时,才会去setExclusiveOwnerThread(null),返回true。
         final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {//首次获得锁
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
             //	已经获得锁,看当前线程是否等于owner线程,表示发生了锁重入
            else if (current == getExclusiveOwnerThread()) {
                //state++
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
        protected final boolean tryRelease(int releases) {
            //state--
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            //只是-1并没有释放锁
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }



版权声明:本文为m0_60181979原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。