ReentrantLock(重入锁)

重入锁定义

如类名可知,锁的类型是可重入锁,是目前JAVA中使用较为广泛的锁,也就是说当前持有锁的线程再次获取不会被阻塞。ReentrantLock支持两种锁:公平锁和非公平锁。如果锁是公平锁那么获取顺序就应该符合请求上的绝对时间顺序,满足FIFO。

ReentrantLock解决如下两个问题:

1.在线程获取锁的时候;如果已经获取锁的线程是当前线程的话则直接再次获取成功;

2.由于锁会被获取n次;那么只有锁在被释放同样的n次之后,该锁才算是完全释放成功。

//可重入锁ReentrantLock,通过其内部实现AbstractQueuedSynchronizer的Sync类来完成锁的功能

public class ReentrantLock implements Lock, java.io.Serializable {

  private final Sync sync;

  //是否生成公平锁实例,默认情况下生成NonfairSync非公平锁.

  public ReentrantLock(boolean fair) {

    sync = fair ? new FairSync() : new NonfairSync();

  }

}

线程加锁(独占)

独占模式加锁分为公平锁与非公平锁,具体加锁的流程分为如下几个步骤:

1,程序通过lock为入口,通过acquire来获取线程锁,这里调用公平锁与非公平锁各自实现中的tryAcquire来实现。

2,当tryAcquire返回true表示抢占锁成功.否则执行如下流程:

3,线程抢占锁失败(addWaiter),先生成一个独占模式的node节点,并把节点添加到队列尾部.

4,通过acquireQueued不断的轮询等待队列,尝试抢占线程锁(其实这里在轮询一次抢占失败后会BLOCKED线程,等待线程的前继节点唤醒后在重新进行抢占).

下面分析下非公平锁与公平锁的实现.

ReentrantLock只实现了Look的独占模式加锁。

非公平锁

ReentrantLock的非公平锁由其内部类”NonFairSync”实现,包含两种情况:

  1. 如果线程来抢占锁资源时,锁没有被其它线程持有,直接设置锁的数量为1,并设置锁的持有线程为当前线程。
  2. 如果锁已经被线程持有,通过AQS.acquire函数尝试线程锁的重入,尝试重入线程锁时非公平锁的实现由Sync.nonfairTryAcquire函数实现。

实现流程如下所示

//ReentrantLock独占模式下非公平锁的加锁流程.

static final class NonfairSync extends Sync {

       //a,ReentrantLock非公平锁的加锁实现

    final void lock() {

        //1,如果是首次加锁,直接设置当前ReentrantLock的所有者为当前线程,并设置锁的数量为1

        if (compareAndSetState(0, 1)) {

            setExclusiveOwnerThread(Thread.currentThread());

        } else {

            //2,这里是线程锁重入,调用AbstractQueuedSynchronizer.acquire来完成加锁.

            

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值