ReentrantLock源码分析

新建Lock时,ReentrantLock默认使用非公平锁进行同步:
public ReentrantLock() {
        sync = new NonfairSync();    // NonfairSync是内部类,实现了Syn内部抽象类

    }

也可以在构造函数传入boolean参数,控制锁的类型,实现如下:
 public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();    // true为公平锁,false为非公平锁

    }

当生成锁后,就可以使用lock()进行线程同步,NonfairSync会先用cas判断锁状态,cas判断失败才会调用acquire(),而FairSync则会直接调用acquire()。ReentrantLock是可重入锁,可以被单个线程多次获取,每获取1次就将锁的状态+1。状态默认为0由于存在两种锁类型,接下来,将优先了解非公平锁重要方法的源码:

final void lock() {
            if (compareAndSetState(0, 1))    // 使用cas机制竞争锁的拥有权
                setExclusiveOwnerThread(Thread.currentThread());    // 设定获得当前锁的线程
            else
                acquire(1);

        }

acquire()的实现代码:
public final void acquire(int arg) {
        if (!tryAcquire(arg) &&    // 尝试获取锁
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 创建一个入队node为当前线程,Node.EXCLUSIVE 是独占锁, Node.SHARED 是共享锁,将线程加入到CLH队列(非阻塞的FIFO队列)末尾。CLH队列就是线程等待队列。
            selfInterrupt();    // 在休眠等待过程中被中断过,acquireQueued会返回true,线程会调用selfInterrupt()中断等待。

    }
首先实行了tryAcquire()尝试获取锁的拥有权,该方法会使用cas机制判断当前的锁是否被拥有,如果当前锁未被拥有,则设置当前线程获得锁;如果被当前线程拥有,则设置state值+1;如果被其他线程拥有则返回false。实现代码如下:
 protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);    // 调用ReentrantLock的Syn抽象内部类
        }
tryAcquire()会调用Syn抽象内部类中的nonfairTryAcquire()方法,如果该锁是FairSync则不会调用nonfairTryAcquire(),而是直接覆盖tryAcquire()。

nonfairTryAcquire()的实现代码:
final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();    // 获取当前线程
            int c = getState();    // 获取锁的状态值
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {    // 如果在cas机制中竞争成功,则设置当前线程获得锁,返回true
                    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;
        }
可以看到ReentrantLock可以被单个线程多次获取,每获取1次就将锁的状态+1。

释放锁:
protected final boolean tryRelease(int releases) {
            int c = getState() - releases;    // 减少状态值
            if (Thread.currentThread() != getExclusiveOwnerThread())    // 判断线程是否拥有锁的线程
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {    // 状态值为0,设置锁的所属线程为null
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }
ReentrantLock释放锁时,会为当前锁的状态值-1,直到状态值为0时,才会释放锁的控制权。

创建Condition,一个ReentrantLock可以有多个Condition实例,可实现分组的等待和唤醒:
final ConditionObject newCondition() {
            return new ConditionObject();

        }

hasQueuedThread()和hasQueuedThreads():
hasQueuedThread(Thread thread)    查询指定的线程是否正在等待获取当前的锁。
hasQueuedThreads()    查询是否有线程正在等待获取当前的锁

getQueueLength():
获取正在等待获取锁的线程数。

getQueuedThreads():
获取正在等待的线程,返回Collection<Thread>。

hasWaiters(Condition condition):
判断绑定了同一个Condition的线程,是否都处于await()状态。

getWaitQueueLength(Condition condition):
获取绑定了用一个Condition,并且处于await()状态的线程数量。

getWaitingThreads(Condition condition):
获取绑定了用一个Condition,并且处于await()状态的线程,返回Collection<Thread>。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值