Java并发编程-AQS源码之条件队列,成功入职腾讯月薪45K

  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();

// t 重新赋值

t = lastWaiter;

}

Node node = new Node(Thread.currentThread(), Node.CONDITION);

// t == null 表示队列此时为空,初始化firstWaiter

if (t == null)

firstWaiter = node;

else

t.nextWaiter = node;

// 将尾指针指向新建的node

lastWaiter = node;

return node;

}

复制代码

上面其实也就是一个单链表的操作. void unlinkCancelledWaiters() 清除队列中已经取消等待的节点

private void unlinkCancelledWaiters() {

Node 需要zi料+ 绿色徽【vip1024b】

t = firstWaiter;

// trail这里表示取消节点的前驱节点

Node trail = null;

while (t != null) {

Node next = t.nextWaiter;

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

t.nextWaiter = null;

if (trail == null)

firstWaiter = next;

else

trail.nextWaiter = next;

if (next == null)

lastWaiter = trail;

}

else

trail = t;

t = next;

}

}

独家面经总结,超级精彩

本人面试腾讯,阿里,百度等企业总结下来的面试经历,都是真实的,分享给大家!

image

image

image

image

Java面试准备

准确的说这里又分为两部分:

  1. Java刷题
  2. 算法刷题

Java刷题:此份文档详细记录了千道面试题与详解;

image

image

0355740626)]

[外链图片转存中…(img-1aIRz2PC-1710355740626)]

Java面试准备

准确的说这里又分为两部分:

  1. Java刷题
  2. 算法刷题

Java刷题:此份文档详细记录了千道面试题与详解;

[外链图片转存中…(img-9wsOUqKg-1710355740626)]

[外链图片转存中…(img-9GO9Rwd7-1710355740627)]

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AQS(AbstractQueuedSynchronizer)是Java并发编程中的一个重要类,它可以理解为抽象的队列同步器。AQS提供了一种基于FIFO队列的同步机制,用于实现各种同步器,如ReentrantLock、CountDownLatch、Semaphore等。 AQS的核心思想是使用一个volatile的int类型变量state来表示同步状态,通过CAS(Compare and Swap)操作来实现对state的原子更新。AQS内部维护了一个双向链表,用于保存等待获取同步状态的线程。 AQS的具体实现包括以下几个方面: 1. 内部属性:AQS内部有两个重要的属性,一个是head,表示队列的头节点;另一个是tail,表示队列的尾节点。 2. 入队操作:AQS的入队操作是通过enq方法实现的。在入队操作中,首先判断队列是否为空,如果为空,则需要初始化队列;否则,将新节点添加到队列的尾部,并更新tail指针。 3. CAS操作:AQS的CAS操作是通过compareAndSetHead和compareAndSetTail方法实现的。这些方法使用CAS操作来更新head和tail指针,保证操作的原子性。 4. 出队操作:AQS的出队操作是通过deq方法实现的。在出队操作中,首先判断队列是否为空,如果为空,则返回null;否则,将头节点出队,并更新head指针。 5. 同步状态的获取和释放:AQS提供了acquire和release方法来获取和释放同步状态。acquire方法用于获取同步状态,如果获取失败,则会将当前线程加入到等待队列中;release方法用于释放同步状态,并唤醒等待队列中的线程。 通过继承AQS类,可以实现自定义的同步器。具体的实现方式是重写AQS的几个关键方法,如tryAcquire、tryRelease等,来实现对同步状态的获取和释放。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值