并发编程(二)-阻塞

本文深入剖析了AQS(AbstractQueuedSynchronizer)在锁竞争后的处理流程,包括尝试获取锁、阻塞、释放锁以及中断唤醒的机制。重点讨论了当线程无法获取锁时如何进入阻塞状态,以及在释放锁时如何唤醒等待的线程,同时详细阐述了中断信号如何影响这一过程。
摘要由CSDN通过智能技术生成

1.锁竞争后的操作-阻塞

开始阻塞

在开始阻塞之前,在尝试获取锁一次

  final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
如果是第一个节点head 再次进行获取加锁的权限 原因是由内核态到用户态的切换很消耗性能,而AQS要尽可能的避免这种切换  注意:再次在此过程中会丢弃最初的head节点也就是买那个空节点,在竞争之后,会把刚加入的那个节点再一次初始化,作为队列的头节点。

判断是否能阻塞

在这里插入图片描述
第一轮循环:
通过首节点的状态判断下一个节点是否能够被唤醒,将head的节点状态更改为-1
第二轮循环:
head的状态已经被改变,可以之后的节点可以被阻塞了,并且判断阻塞是否是由中断信号引起的
在这里插入图片描述

开始释放锁

在这里插入图片描述
开始释放锁,head节点的状态由0 --> -1 线程已经被唤醒去竞争加锁,对于公平锁,直接去获取锁没有问题,head节点会被直接抛弃,当前的node节点会成为新的head的节点;但是对于非公平锁而言,线程被唤醒的同时会有外面进来的线程同时竞争加锁的权限,若成功,和公平锁一致;若是失败,线程将再次被阻塞,注意,此次阻塞不会把线程添加到阻塞队列的队尾,而是通过修改node节点的前驱节点的状态,再一次将其阻塞,即head的节点状态再次有-1–>0

唤醒-中断和release

在这里插入图片描述
中断唤醒:
在这里插入图片描述
在这里插入图片描述
中断后会改变指向该线程的节点的状态,doAcquireInterruptibly(int arg)方法会把节点状态更改为cancel状态,在阻塞队列中剔除,执行中断后的逻辑。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值