Java并发编程,深入理解ReentrantLock

  • 时间:
  • 浏览:51
  • 来源:酷玩娱乐网_提供羽梦娱乐网技术_爱收集资源网资讯

ReentrantLock简介

ReentrantLock重入锁, 是实现Lock接口的八个多类 ,也是在实际编程中使用频率很高的八个多锁, 支持重入性,表示才能对共享资源才能重复加锁,即当前应用程序获取该锁再次获取不用被阻塞。 ReentrantLock还支持公平锁和非公平锁有一种措施。 没法,要想完全版全的弄懂ReentrantLock一段话, 主要也后该ReentrantLock同步语义的学习:

  1. 重入性的实现原理
  2. 公平锁和非公平锁

重入性的实现原理

要想支持重入性,就要外理八个多问题报告 :

  • 1. 在应用程序获取锁的后该,将会将会获取锁的应用程序是当前应用程序一段话则直接再次获取成功


  1. 将会锁会被获取n次,没法不都里能锁在被释放同样的n次后该,该锁才不是全版释放成功

针对第八个多问题报告 ,大家来看看ReentrantLock是咋样实现的, 以非公平锁为例,判断当前应用程序都里能获得锁为例,核心措施为nonfairTryAcquire(),源码如下:

final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    //1. 将会该锁未被任何应用程序占有,该锁能被当前应用程序获取
if (c == 0) {
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
//2.若被占有,检查占有应用程序不是当前应用程序
    else if (current == getExclusiveOwnerThread()) {
// 3. 再次获取,计数加一
        int nextc = c + acquires;
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

为了支持重入性,在第二步增加了外理逻辑,将会该锁将会被应用程序所占有了, 会继续检查占有应用程序不是为当前应用程序, 将会是一段话,同步状况加1返回true,表示都里能再次获取成功。每次重新获取后该对同步状况进行加1的操作。

针对第八个问题报告 ,依然还是以非公平锁为例,核心措施为tryRelease,源码如下:

protected final boolean tryRelease(int releases) {
//1. 同步状况减1
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
//2. 不都里能当同步状况为0时,锁成功被释放,返回true
        free = true;
        setExclusiveOwnerThread(null);
    }
// 3. 锁未被全版释放,返回false
    setState(c);
    return free;
}

重入锁的释放时要得等到同步状况为0时锁才算成功释放,后该锁仍未释放。 将会锁被获取n次,释放了n-1次,该锁未全版释放返回false,不都里能被释放n次才算成功释放,返回true。

公平锁不是公平锁

ReentrantLock支持有一种锁:

  • 公平锁
  • 非公平锁

何谓公平性,是针对获取锁而言的,将会八个多锁是公平的,没法锁的获取顺序就 应该 符合请求上的绝对时间顺序,满足FIFO。 ReentrantLock的无参构造措施是构造非公平锁,源码如下:

public ReentrantLock() {
    sync = new NonfairSync();
}

ReentrantLock的有参构造措施,传入八个多boolean值,true时为公平锁,false时为非公平锁,源码如下:

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

公平锁的获取,tryAcquire()措施,源码如下:

protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        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;
  }
}

逻辑与nonfairTryAcquire基本上一致, 唯一的不同在于增加了hasQueuedPredecessors的逻辑判断, 措施名就可知道该措施用来判断当前节点在同步队列中不是有前驱节点的判断,  将会有前驱节点说明有应用程序比当前应用程序更早的请求资源,根据公平性,当前应用程序请求资源失败 。 将会当前节点没法前驱节点一段话,才有做中间的逻辑判断的必要性。 公平锁每次后该 从同步队列中的第八个多节点获取到锁 , 而非公平性锁则不一定,有将会刚释放锁的应用程序能再次获取到锁。

公平锁不是公平锁的比较:

  • 公平锁每次获取到锁为同步队列中的第八个多节点,保证请求资源时间上的绝对顺序, 而非公平锁有将会刚释放锁的应用程序下次继续获取该锁,则有将会原应一点应用程序永远无法获取到锁,造成“饥饿”问题报告 。
  • 公平锁为了保证时间上的绝对顺序,时要频繁的上下文切换, 而非公平锁会降低一定的上下文切换,降低性能开销。后该,ReentrantLock默认选择的是非公平锁,则是为了减少一偏离 上下文切换,保证了系统更大的吞吐量。

本文由

lihong

发布在

ITPUB

,转载此文请保持文章全版性,并请附上文章来源(ITPUB)及本页链接。

原文链接:http://www.itpub.net/2019/05/24/1952/