Hi,are you ready?

准备好开始了?
那就与我们取得联系吧

有一个品牌项目想和我们谈谈吗?您可以填写右边的表格,让我们了解您的项目需求,这是一个良好的开始,我们将会尽快与你取得联系。当然也欢迎您给我们写信或是打电话,让我们听到你的声?

?址:

?话:

E-mail:

从 ReentrantLock 的实现看 AQS 的原理及应用

作者:admin 时间:2020-10-30

一般来说,自界说同步器要么是独占办法,要么是同享办法,它们也只需完结 tryAcquire-tryRelease、tryAcquireShared-tryReleaseShared 中的一种即可。AQS 也支撑自界说同步器一起完结独占和同享两种办法,如 ReentrantReadWriteLock。ReentrantLock 是独占锁,所以完结了 tryAcquire-tryRelease。

以非公正锁为例,这儿首要论述一下非公正锁与 AQS 之间办法的相关之处,详细每一处中心办法的效果会在文章后边详细进行论述。

为了协助咱们了解 ReentrantLock 和 AQS 之间办法的交互进程,以非公正锁为例,咱们将加锁和解锁的交互流程独自拎出来着重一下,以便于对后续内容的了解。

加锁:

解锁:

经过上面的描绘,大约能够总结出 ReentrantLock 加锁解锁时 API 层中心办法的映射联系。

ReentrantLock 中公正锁和非公正锁在底层是相同的,这儿以非公正锁为例进行剖析。

在非公正锁中,有一段这样的代码:

 仿制代码

// java.util.concurrent.locks.ReentrantLock
static final class NonfairSync extends Sync {
 final void lock {
 if )
 setExclusiveOwnerThread);
 else
 acquire;
}

看一下这个 Acquire 是怎样写的:

 仿制代码

// java.util.concurrent.locks.AbstractQueuedSynchronizer
public final void acquire {
 if  acquireQueued, arg))
 selfInterrupt;
}

再看一下 tryAcquire 办法:

 仿制代码

// java.util.concurrent.locks.AbstractQueuedSynchronizer
protected boolean tryAcquire {
 throw new UnsupportedOperationException;
}

能够看出,这儿仅仅 AQS 的简略完结,详细获取锁的完结办法是由各自的公正锁和非公正锁独自完结的。假如该办法回来了 True,则阐明当时线程获取锁成功,就不必往后履行了;假如获取失利,就需求参加到等候行列中。下面会详细解说线程是何时以及怎样被参加进等候行列中的。

当履行 Acquire 时,会经过 tryAcquire 获取锁。在这种状况下,假如获取锁失利,就会调用 addWaiter 参加到等候行列中去。

获取锁失利后,会履行 addWaiter 参加等候行列,详细完结办法如下:

 仿制代码

// java.util.concurrent.locks.AbstractQueuedSynchronizer
private Node addWaiter {
 Node node = new Node, mode);
 // Try the fast path of enq; backup to full enq on failure
 Node pred = tail;
 if  {
 node.prev = pred;
 if ) {
 pred.next = node;
 return node;
 enq;
 return node;
private final boolean compareAndSetTail {
 return unsafe.compareAndSwapObject;
}

首要的流程如下:

经过当时的线程和锁方式新建一个节点。

Pred 指针指向尾节点 Tail。

将 New 中 Node 的 Prev 指针指向 Pred。

经过 compareAndSetTail 办法,完结尾节点的设置。这个办法首要是对 tailOffset 和 Expect 进行比较,假如 tailOffset 的 Node 和 Expect 的 Node 地址是相同的,那么设置 Tail 的值为 Update 的值。

 仿制代码

// java.util.concurrent.locks.AbstractQueuedSynchronizer
static {
 try {
 stateOffset = unsafe.objectFieldOffset);
 headOffset = unsafe.objectFieldOffset);
 tailOffset = unsafe.objectFieldOffset);
 waitStatusOffset = unsafe.objectFieldOffset);
 nextOffset = unsafe.objectFieldOffset);
 } catch  { 
 throw new Error; 
}

从 AQS 的静态代码块能够看出,都是获取一个目标的特点相关于该目标在内存傍边的偏移量,这样咱们就能够依据这个偏移量在目标内存傍边找到这个特点。tailOffset 指的是 tail 对应的偏移量,所以这个时分会将 new 出来的 Node 置为当时行列的尾节点。一起,由所以双向链表,也需求将前一个节点指向尾节点。

假如 Pred 指针是 Null,或许当时 Pred 指针和 Tail 指向的方位不同,就需求看一下 Enq 的办法。

 仿制代码

// java.util.concurrent.locks.AbstractQueuedSynchronizer
private Node enq {
 for  {
 Node t = tail;
 if  { // Must initialize
 if ))
 tail = head;
 } else {
 node.prev = t;
 if ) {
 t.next = node;
 return t;
}

假如没有被初始化,需求进行初始化一个头结点出来。但请留意,初始化的头结点并不是当时线程节点,而是调用了无参结构函数的节点。假如阅历了初始化或许并发导致行列中有元素,则与之前的办法相同。其实,addWaiter 便是一个在双端链表添加尾节点的操作,需求留意的是,双端链表的头结点是一个无参结构函数的头结点。

总结一下,线程获取锁的时分,进程大体如下:

a. 当没有线程获取到锁时,线程 1 获取锁成功。

b. 线程 2 请求锁,可是锁被线程 1 占有。

c. 假如再有线程要获取锁,顺次在行列中往后排队即可。

回到上边的代码,hasQueuedPredecessors 是公正锁加锁时判别等候行列中是否存在有用节点的办法。假如回来 False,阐明当时线程能够争夺同享资源;假如回来 True,阐明行列中存在有用节点,当时线程有必要参加到等候行列中。

 仿制代码

// java.util.concurrent.locks.ReentrantLock
public final boolean hasQueuedPredecessors {
 // The correctness of this depends on head being initialized
 // before tail and on head.next being accurate if the current
 // thread is first in queue.
 Node t = tail; // Read fields in reverse initialization order
 Node h = head;
 Node s;
 return h != t  == null || s.thread != Thread.currentThread);
}

看到这儿,咱们了解一下 h != t == null || s.thread != Thread.currentThread); 为什么要判其他头结点的下一个节点?第一个节点贮存的数据是什么?

双向链表中,第一个节点为虚节点,其实并不存储任何信息,仅仅占位。实在的第一个有数据的节点,是在第二个节点开端的。当 h != t 时:

a. 假如 == null,等候行列正在有线程进行初始化,但仅仅进行到了 Tail 指向 Head,没有将 Head 指向 Tail,此刻行列中有元素,需求回来 True。

b. 假如 != null,阐明此刻行列中至少有一个有用节点。假如此刻 s.thread == Thread.currentThread,阐明等候行列的第一个有用节点中的线程与当时线程相同,那么当时线程是能够获取资源的;假如 s.thread != Thread.currentThread,阐明等候行列的第一个有用节点线程与当时线程不同,当时线程有必要参加进等候行列。

 仿制代码

// java.util.concurrent.locks.AbstractQueuedSynchronizer
  
返回列表

RELATED CASE

相关案例

网络建设设计公司

从 ReentrantLock 的实现看 AQS 的原理及应用

一般来说,自界说同步器要么是独占办法...

网络建设设计公司

广州白云区市场监管局助力企业复产,驻

南都讯疫情迸发后,白云区商场监管局对...

网络建设设计公司

年夜饭变牢饭!春节前夕,互联网公司反

年关将至,互联网公司举起了“反腐”的...

网络建设设计公司

浪潮专家解读:HPC如何协助解析新型冠状

在不知道病毒以 不明原因肺炎 进入大众...

Are you interested in ?

感兴趣吗?

有关我们服务的更多信息,请联系

与我们合作

与我们合作,您将会得到更成熟的品牌建设服务。我们以客户至上,同时也相互挑战,力求呈现最好的品牌建设成果。

品牌咨询热线:

TOP