美文网首页
ReentrantLock可重入锁理解

ReentrantLock可重入锁理解

作者: 南柯太守_5f33 | 来源:发表于2018-09-27 10:22 被阅读0次

主要功能:

  • 资源独占以及唤醒

  • 同一线程可重复进入

  • 公平锁: 如果无锁等待队列, 再尝试获取锁; 非公平锁, 先尝试获取锁,获取不到进入等待队列

实现原理:

利用AQS的的state状态来判断资源是否已锁,同一线程重入加锁,state的状态+1; 同一线程重入解锁,state状态-1(解锁必须为当前独占线程,否则异常); 当state为0时解锁成功。

代码解读:

数据结构

//锁的操作是基于AQS来实现的
private final Sync sync;
//默认非公平锁
public ReentrantLock() {
        sync = new NonfairSync();
}
//可选公平和非公平锁
public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
}

非公平锁的获取

//abstract static class Sync extends AbstractQueuedSynchronizer
//非公平锁获取
final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //直接CAS抢锁
                if (compareAndSetState(0, acquires)) {
                    //抢到锁则把当前线程设置为独占线程
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                //同线程重入, 状态加1
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                //同一线程重入,无线程竞争,无需CAS操作
                setState(nextc);
                return true;
            }
            return false;
        }

公平锁的获取

//公平锁,锁获取操作
protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //线程状态为已解锁,无等待队列再去获取锁
                //!hasQueuedPredecessors为与非公平锁的差异点
                if (!hasQueuedPredecessors() &&
                    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;
        }

锁释放操作

//abstract static class Sync extends AbstractQueuedSynchronizer
//锁释放
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);
            }
           //锁持有计数减1,同线程内无需CAS
            setState(c);
            return free;
        }

相关文章

网友评论

      本文标题:ReentrantLock可重入锁理解

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