reentrantlock非公平锁不会随机挂起线程?_深入理解ReentrantLock

前言

ReentrantLock是java.util.concurrent.locks包中的一个类,是独占锁,为最后一个执行lock操作成功且为释放锁的线程锁拥有.因为它是基于AQS实现的,先看下它和Synchronized的区别

  • 便利性:Synchronized用法更简洁,由编译器去保证锁的加锁和释放; ReenTrantLock需要手动加锁和释放锁,为了避免忘记手工释放锁造成死锁,所以最好在finally中声明释放锁。
  • 锁的细粒度和灵活度:ReenTrantLock优于Synchronized

此外,以下特点是ReenTrantLock独有:

1. ReenTrantLock可以指定是公平锁还是非公平锁; synchronized只能是非公平锁。

2. ReenTrantLock提供了一个Condition类,用来实现唤醒特定的线程; synchronized要么随机唤醒一个线程要么唤醒全部线程。

3. ReenTrantLock提供了一种能够中断等待锁的线程的机制。

接下来看下它的构成

bf813b0c67c2dd359c274397665290cf.png

Sync定义了abstract void lock();它的两个子类分别对其进行了实现,下面我们开始了解Sync

Sync.java

  • nonfairTryAcquire(Sync中默认采用非公平方式尝试获取锁)
final 

如果当前锁未被任何线程拥有(state==0),则通过compareAndSetState原子地设置state,然后把当前线程设置为自己,获取成功;

如果当前锁已经被线程占有,判断持有锁的线程是否为当前线程,若是,nextc+ acquires,获取成功;否则获取失败.

如果在它之前已经有很多线程等待锁,最后却被他获取,这里体现了非公平性.

  • 尝试释放所 :tryRelease
protected 

如果当前线程并非锁持有者,throw new IllegalMonitorStateException();如果是当前锁持有者,state减去release,判断state值,如果为0,说明完全释放,否则,还未完全释放.

接下来是一些简单的方法,就不解释了,直接看源码

protected 

NonfairSync.java

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);
    }

protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
    }
}

关于acquire方法,请参考深入学习java同步器

FairSync.java

static 

在FairSync类的tryAcquire中会通过hasQueuedPredecessors()方法判断AQS的等待队列中是否前继节点,如果有,则不执行.这里体现了获取锁的公平性,等待越久的线程越先获取到锁

ReentrantLock.java

//默认使用非公平锁

AQS$hasQueuedThreads

public 

AQS的等待队列中,是否有等待该条件的线程

我是伯仁,如果觉得文章对您有帮助,欢迎点赞关注.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值