Java并发包下锁学习第三篇-锁是怎么维护内部队列的

从源码学习Java并发的锁是怎么维护内部线程队列的

在上一篇文章中,凯哥对同步组件基础框架- AbstractQueuedSynchronizer(AQS)做了大概的介绍。我们知道AQS能够通过X 7 _内置的FIFO队列来完T . O | I Q成资源获取线程的排队工作。那么AQSX 8 ^是怎么N T Z ^来维护这个排队工作的呢? x ] - 0 y n ] *今天我们就来扒一扒AQS源码。从源码中来M ~ 6 :看看是怎么维护对了的。

本篇是《凯哥(凯哥Java:kagejava)并发编程学习》系列之《Lock系列》教程的第一篇:《Java并) b K发包下锁学习第三篇-从源码学习Java并发是怎么维护内部线程队列的》。

在上篇我们知道AQS内部有个c o -内部类-Node对象。这个对象就是来维护线程对资源访问的排队工作的。具体怎么操作的呢?本文主要内容:Node节点介绍;在同步器中i R o x x c O怎么为维护排队的流程图。

一:Node节点对象介c Q 0 B } e N

在AQS内部有个Node对象的内部类。我们来看看这个对象都有哪些属性:

Java并发包下锁学习第三篇-锁是怎么维护内部队列的

简化后:

Java并发包下锁学习第三篇-锁是怎么维护内部队列的

对象中属性介绍

Int waiY j ] ) ctStatus:

对象里面有表示状态的4个属性:

static final i( - z #nt CANCELLED = 1:线程从同步队列中取消

static final inG t T t lt SIGNAL = -1:后续节点等待状态。当前节点在获取到资L f ~ F K S : K }源后,在释放前需要断开和后续节点的连接。在其释放F [ M O后,会通知后续节点,使后续解决继续运行。

staB [ &tic final int CONDITION = -2:当前节点等待中。在等待co) @ h h 9 D 2 ;ndit, } aion通知。也可以理解成在condition队列中。

static final int PROPAGATE = -3:在共享模式下,下一次无条件传播

0:默认状? ~ 9 | K Q v态。

Node prev:当前节点G [ L l *的上一个节点

Node Next:当前p ) | W - - 7 q解决的后续节点

Node nextWait9 @ Ler:可以理解为节点的j T ! O V V类型。是共享式还是独占式。

Thread thread:当前获取到同步状态的线程对象。

具体可以如下图:

Java并发包下锁学习第三篇-锁是怎么维护内部队列的

首先,我们需要明白,在数据D ^ A结构中,能够保持FIFO的结构是队列模式的。但是队列有单项队列和循环队列G 2 N 3 z两种。那么,同步器使用的是哪个队列方式呢?

从Node节点属性中,我们A # x j可以看到前节点和后续节点的属性。说明使用的是循环队列。

二:维护线程排队的流程图

为了保证线程Q c N E v的安全,同步器提供了几个CAS的方法。如下图:

Java并发包下锁学习第三篇-锁是怎么维护内部队列的

CAS设置头Q S y节点、设置下一个节点、设置状态、设置尾节9 ~ z d R点等。

操作流程可以简述如下图:

Java并发包下锁学习第三篇-锁是怎么维护内部队列的

流程说明:

入队列

入队流程如下:

Java并发包下锁学习第三篇-锁是怎么维护内部队列的

上图流程说明:

当多个线程同V w P H q d 6时来争夺资源的时候,其中一个线程获取到了资源(同步状态或者是锁),这个时候获取到资P O l源的线程u ( x ! X就会被构造成头节点。其他线无非获取到资源的线程会被构成成Node节点对象并被放到队列中。被构造成Node节点的线程会排在队列尾部排队。为了保证线程安全性,同步器会基于Cx / 7 { N z .AS设置尾节点的方法(即:compareAndSetTail ())来保持线程安全性.这个方法需要传递当前线程\"自己认为\"的尾节点和前一个节2 e ^ 9点,当CAS执行成功之后,当前节点才会正式与之前的节点建立j : O关系。被设置尾部的Node节点的next将指向头节点。

如上图中线程3会和线程1执行类似的操作,把自己添加到队列的尾部。这样就形成了一个完整的双向队列排队了。

出队列

出队流程图如下:

Java并发包下锁学习第三篇-锁是怎么维护内部队列的

出队流程说明:

从入队流程图中我们可以看出,所有争夺资源并发的线程都被排队了。同步队列遵循FIFO(先? 1 T a / . + w c进先出)。所谓的首节点就是获取同b h % J F j i步状态成功节点。当来的首节点中的线程在释放同步状态的时候,会a 5 9 4 5 + F ~断开自己与后续节点的关联关系,然后会唤醒后续节点操作的。当后续节点获取同步状态成功的时候,就将自己设置为首节点,原来的首节点就退出了队列。如果原来的首节点还需要获取的话,后将自己线程构造成Nodei p b节点对象,然后进行排队。

上一篇

电商平台能否解决第三方医学检验出现的问题?

下一篇

疫情过后,这些投资机会也许是你的财富起点

你也可能喜欢

  • 暂无相关文章!

发表评论

您的电子邮件地址不会被公开。 必填项已用 * 标注

提示:点击验证后方可评论!

插入图片
返回顶部