Java一面:AQS 了解吗?一文深入剖析底层原理及避坑
2021-06-08 00:02
标签:阿里 线程等待 sem 共享资源 air 执行 exception ica vol AQS( AQS 维护了一个 state(共享资源变量)和一个 FIFO 线程等待队列(CLH 队列),多个线程竞争 state 被阻塞时就会进入此队列中。 state 使用 volatile 修饰的一个 int 类型的共享资源变量 资源共享的两种方式: 简短说就是一个双向链表,使用内部类 Node 来实现的。head、tail 指针分别指向链表的头部和尾部。 我们一般常用的写法如下: 那在加锁和解锁的具体过程究竟是怎么样的呢,肥壕举了两个比较简单的例子 线程 A、B、C 同时抢占锁,此时线程 B 抢占成功,线程 A、C 则失败,具体流程如下: 此时线程 B 执行完业务逻辑后,调用 lock.unlock(),具体流程如下: 这也是平时面试经常被问到的一个问题,这里简要谈一谈 具体相关代码可以看 ReentrantLock 下的两个静态类 FairSync、NonFairSync ReentrantLock 中可以通过 newCondition() 方法创建一个 Condition 对象,那这个对象究竟是啥玩意呢? 简单说,替代传统的 Object 的 wait()、notify() 实现线程间的协作。 先来看一个使用实例: 线程 A、B、C、D 同时启动抢占锁,这时抢占成功的线程会执行自己的逻辑业务,抢占失败的就会像上面所说,进入线程CLH 队列中。 假设线程 B 先获取锁,调用 condition.await() 方法后释放锁,阻塞并进入条件等待队列,线程 A 、C 获取锁后也依次进入条件等待队列。 线程 D 获取锁后调用 condition.signalAll() 方法,它会将条件等待队列中的线程放入 CLH 队列,并唤醒所有的等待线程。 注意,条件队列中的线程是依次一个一个加入 CLH 队列的队尾。 LockSupport 在 AQS 中,队列中线程的阻塞唤醒都是通过 LockSupport 实现的。 LockSupport 类,是用来创建锁和其他同步类的基本线程阻塞原理,核心方法只要看这两个: park() :阻塞当前调用线程 unpark():唤醒指定线程 相比Object 类中的 wait()、notify()、notifyAll(),区别是: 【免责声明:本文图片及文字信息均由千锋重庆Java培训小编转载自网络,旨在分享提供阅读,版权归原作者所有,如有侵权请联系我们进行删除。】 Java一面:AQS 了解吗?一文深入剖析底层原理及避坑 标签:阿里 线程等待 sem 共享资源 air 执行 exception ica vol 原文地址:https://www.cnblogs.com/cqqfboy/p/14547307.html实现原理
AbstractQueuedSynchronizer),抽象的队列式同步器State
CLH 队列(FIFO)
ReentrantLock lock = new ReentrantLock();
// 加锁
lock.lock();
// 业务逻辑代码
...
// 解锁
lock.unLock();
场景分析
加锁
解锁
公平锁与非公平锁
Condition
public class Demo {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void methodAwait() {
try {
lock.lock();
System.out.println(String.format("### 当前线程:%s waiting ###", Thread.currentThread().getName()));
condition.await();
System.out.println(String.format("### 当前线程:%s finished ###", Thread.currentThread().getName()));
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void methodSignal() {
try {
lock.lock();
System.out.println(String.format("### 当前线程:%s signal ###", Thread.currentThread().getName()));
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Demo demo = new Demo();
Thread t1 = new Thread(() -> demo.methodAwait(),"thread-A");
Thread t2 = new Thread(() -> demo.methodAwait(), "thread-B");
Thread t3 = new Thread(() -> demo.methodAwait(), "thread-C");
Thread t4 = new Thread(() -> demo.methodSignal(), "thread-D");
t1.start();
t2.start();
t3.start();
Thread.sleep(2000);
t4.start();
}
}
扩展
上一篇:MSBUILD : error MSB3428: 未能加载 Visual C++ 组件“VCBuild.exe”。
下一篇:【数据结构】算法 Remove Duplicates from Sorted List 2 删除排序链表中的重复元素
文章标题:Java一面:AQS 了解吗?一文深入剖析底层原理及避坑
文章链接:http://soscw.com/essay/91960.html