Java并发编程-AQS源码之条件队列,Java高级工程师必看系列

Thread thread2 = new Thread(()->{

String name = Thread.currentThread().getName();

lock.lock();

System.out.println(name + “==>成功获取到锁” + lock);

try {

System.out.println(“========== 线程1:条件队列await,没有被signal的时候会一直等着 ===========”);

Thread.sleep(10000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(name + “==>通知等待队列的线程”);

condition.signal();

lock.unlock();

System.out.println(name + “==>释放锁”);

}, “线程2”);

thread2.start();

}

}

复制代码

执行结果:

image.png

1.2 源码分析

AQS,Lock,Condition,ConditionObject之间的关系:

以ReentrantLock为例, ConditionObject是AQS的内部类,实现了Condition接口,Lock中提供newCondition()方法,委托给内部AQS的实现Sync来创建ConditionObject对象,享受AQS对Condition的支持。

image.png

从上面的例子可以看出,条件队列的流程大概是这样 lock -> await -> signal -> unlock

waitStatus可以取五种状态:

  1. 初始化为0,啥也不表示,之后会被置signal。
  1. 1表示cancelled,取消当前线程对锁的争夺。
  1. -1表示signal,表示当前节点释放锁后需要唤醒后面可被唤醒的节点。
  1. -2表示condition,我们这篇的重点,表示当前节点在条件队列中
  1. -3表示propagate,表示释放共享资源的时候会向后传播释放其他共享节点。

1.2.1 等待队列

等待队列是一个FIFO的队列,在队列中的每个节点都包含了一个线程引用,该线程就是在Condition对象上等待的线程,如果一个线程调用了Condition.await()方法,那么该线程将会释放锁、构造成节点加入等待队列并进入等待状态。

image.png

Condition拥有首尾节点的引用,而新增节点只需要将原有的尾节点nextWaiter指向它,并且更新尾节点即可。

同步队列和等待队列之间的关系

image.png

Condition的实现是同步器的内部类,因此每个Condition实例都能够访问同步器提供的方法,相当于每个Condition都拥有所属同步器的引用

1.2.2 等待

await代码

public final void await() throws InterruptedException {

// 1. 当前线程被中断,直接抛出异常

if (Thread.interrupted())

throw new InterruptedException();

// 2. 添加到条件队列中

Node node = addConditionWaiter();

// 3. 释放同步资源,锁

int savedState = fullyRelease(node);

int interruptMode = 0;

// 4. 如果这个节点的线程不在同步队列中,说明该线程还不具备竞争锁的资格

while (!isOnSyncQueue(node)) {

// 挂起线程

LockSupport.park(this);

// 线程中断退出

if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)

break;

}

// 退出循环,被唤醒之后,进入阻塞队列,等待获取锁 acquireQueued

if (acquireQueued(node, savedState) && interruptMode != THROW_IE)

interruptMode = REINTERRUPT;

if (node.nextWaiter != null) // clean up if cancelled

unlinkCancelledWaiters();

if (interruptMode != 0)

reportInterruptAfterWait(interruptMode);

}

复制代码

Node addConditionWaiter() 添加到条件队列

private Node addConditionWaiter() {

Node t = lastWaiter;

// If lastWaiter is cancelled, clean out.

if (t != null && t.waitStatus != Node.CONDITION) {

// 遍历整个条件队列,将已取消的所有节点清除出列

unlinkCancelledWaiters();

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

jQLLXlDB-1710825639473)]
[外链图片转存中…(img-4eOxfJi2-1710825639473)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-TKirhdWT-1710825639474)]

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值