06 | 锁:如何理解锁的同步阻塞队列与条件队列?
锁的基本存储结构
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了并发编程中的关键概念——锁的原理和底层实现机制。通过生动的比喻和具体的代码示例,读者可以快速了解锁的排他性和资源保护概念,以及锁的基本存储结构和底层实现原理。文章详细介绍了AQS(AbstractQueuedSynchronizer)的类图和各个类的含义,以及ReentrantLock对标synchronized的实现原理。重点解析了锁的申请过程,包括tryLock方法和tryAcquireNanos方法的实现细节,以及CAS(比较-交换)机制在锁申请中的重要作用。此外,文章还对AQS的内部数据结构和方法进行了深入解析,帮助读者更加深入地理解锁的本质和实现原理。总体而言,本文通过生动的比喻和具体的代码示例,将抽象的并发编程概念具体化,使读者能够快速了解锁的同步阻塞队列与条件队列的概念及其底层实现机制。文章内容涵盖了锁的释放、条件等待队列等关键概念,为读者提供了全面的并发编程知识。
《中间件核心技术与实战》,新⼈⾸单¥59
全部留言(9)
- 最新
- 精选
- 末日,成欢对于AQS框架的理解, 我的感觉它更像是synchronized的JAVA实现。 在进入synchronized代码内部的时候, 是通过monitorenter指令, 修改了对象头的Markword. AQS在进入的时候, 通过CAS修改了state变量。 释放的时候同理。 当多个线程阻塞排队的时候, synchonized同样存在入口的等待队列EntryList,和AQS类似。 当使用wait/notifyAll的时候, synchronized同样存在条件队列waiSet, 也和AQS的条件队列类似。 持有线程ownerThread,也是类似的。 AQS又是对synchronized的功能的增强。 比如增加了非阻塞式锁,支持打断式获取锁、支持超时式获取锁。 并且大师们更对AQS实现了公平锁、非公平锁,还有一些更好用的工具类。 ReentrantReadWriteLock也是使用AQS实现的。 它对state的高低16位有更多的功能。 读用的是高16位,写用的是低16位 并且读锁使用的是共享模式, 也就是当写锁释放时, 会将读线程一个一个唤醒。
作者回复: 嗯,对的,非常不错,我当时就认真看了大师写的AQS,才真正对锁有了正确的认知,正确认知锁后,对多线程并发编程就能得心应手。
2022-07-23归属地:上海8 - 码小呆感觉一遍还不够我大脑理解,需要多看看!
作者回复: 你好,在看的过程中,如果有什么疑问,可以找我细聊
2022-06-261 - :)老师,你好, 看了下源码ReentrantLock 是 implements Lock 而不是 extends ,为什么还用内部类Sync,而不是直接extends AbstractQueuedSynchronizer?
作者回复: 你好,你这个问题问的非常好。我发表一下我的一些看法,欢迎探讨执教。 这里其实涉及到设计模式的一些实践。 AbstractQueuedSynchronizer 这个类,主要用来定义一些锁的共同方法,锁的一些模版方法,但锁的类型有读写锁、公平锁,公平锁、信号量、CountDownlatch,这些都有一些共性方法,但他们之间又很多差异,如果继承一个基类,由于存在较大差异,代码会很乱,并且受限于java单继承机制,所以就采用来内部类,来解决多重继承,并且引入两个维度。
2022-06-25归属地:上海21 - 小豹哥这也太仔细认真了吧,这细节抠的! 给老师点个大大的赞
作者回复: 谢谢认可,之所以我在这花这么大的篇幅在介绍juc中锁的实现,是因为我从一个毫无高并发编程经验的菜鸟,慢慢通过研读juc这块的代码,从而对多线程编程有了实打实的在原理层面的开窍,就是有那种悟道、豁然开朗的感觉。
2022-06-24归属地:上海1 - TableBear老师,请问你的源码是JDK什么版本的?
作者回复: 你好,使用的版本是jdk1.8的
2022-07-062 - 雨落~紫竹我又来了
作者回复: 谢谢你的互动,期待我们更多的技术碰撞,一起进步。
2022-07-02 - smilekaka太干了,有点噎住....2023-07-26归属地:江苏
- 小麦“如果节点的状态为 Node.CONDITION,或者 node.prev 为空,表示线程在等待条件被触发。为什么节点的前驱节点不为空就可以认为线程在同步阻塞队列中呢?这是因为进入同步队列时是用 CAS 机制来更新前驱节点的。” AQS 貌似没有通过 CAS 更新前驱节点的操作。 private static final long stateOffset; private static final long headOffset; private static final long tailOffset; private static final long waitStatusOffset; private static final long nextOffset; 没看到有前驱节点的偏移量。2022-08-04归属地:广东
- Zx有一个小问题请教老师,为什么唤醒节点要从队尾开始找最靠前的非取消节点,而不是从队头开始找呢2022-06-271