文章目录
- 🌟 一、AQS的底层实现原理
- 🍊 1. AQS的概述
- 🍊 2. AQS的数据结构
- 🎉 (1) 同步状态
- 🎉 (2) 等待队列
- 🍊 3. AQS的锁请求和释放过程
- 🎉 (1) 独占模式
- 🎉 (2) 共享模式
- 🍊 4. AQS的实战使用场景
- 🎉 (1) ReentrantLock
- 🎉 (2) Semaphore
- 🎉 (3) CountDownLatch
- 🍊 5. AQS的问题和解决方案
- 🎉 (1) 饥饿
- 🎉 (2) 死锁
- 🌟 二、总结
📕我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作者、产品软文创造者、技术文章评审老师、问卷调查设计师、个人社区创始人、开源项目贡献者。🌎跑过十五公里、徒步爬过衡山、🔥有过三个月减肥20斤的经历、是个喜欢躺平的狠人。
📘拥有多年一线研发和团队管理经验,研究过主流框架的底层源码(Spring、SpringBoot、Spring MVC、SpringCould、Mybatis、Dubbo、Zookeeper),消息中间件底层架构原理(RabbitMQ、RockerMQ、Kafka)、Redis缓存、MySQL关系型数据库、 ElasticSearch全文搜索、MongoDB非关系型数据库、Apache ShardingSphere分库分表读写分离、设计模式、领域驱动DDD、Kubernetes容器编排等。🎥有从0到1的高并发项目经验,利用弹性伸缩、负载均衡、报警任务、自启动脚本,最高压测过200台机器,有着丰富的项目调优经验。
📙经过多年在CSDN创作上千篇文章的经验积累,我已经拥有了不错的写作技巧。同时,我还与清华大学出版社签下了四本书籍的合约,并将陆续在明年出版。这些书籍包括了基础篇、进阶篇、架构篇的📌《Java项目实战—深入理解大型互联网企业通用技术》📌,以及📚《解密程序员的思维密码–沟通、演讲、思考的实践》📚。具体出版计划会根据实际情况进行调整,希望各位读者朋友能够多多支持!
希望各位读者大大多多支持用心写文章的博主,现在时代变了,信息爆炸,酒香也怕巷子深,博主真的需要大家的帮助才能在这片海洋中继续发光发热,所以,赶紧动动你的小手,点波关注❤️,点波赞👍,点波收藏⭐,甚至点波评论✍️,都是对博主最好的支持和鼓励!
- 💂 博客主页: 我是廖志伟
- 👉开源项目:java_wxid
- 🌥 哔哩哔哩:我是廖志伟
- 🎏个人社区:幕后大佬
- 🔖个人微信号:
SeniorRD
💡在这个美好的时刻,本人不再啰嗦废话,现在毫不拖延地进入文章所要讨论的主题。接下来,我将为大家呈现正文内容。
🌟 一、AQS的底层实现原理
🍊 1. AQS的概述
AQS(AbstractQueuedSynchronizer)是Java提供的一个同步框架,它可以用来实现锁和其他同步工具。AQS的核心思想是共享状态的管理,它通过一个int型的volatile变量来描述同步状态,同时维护一个FIFO队列,用来存放等待线程。在AQS的实现中,同步状态的修改和FIFO队列的维护是通过CAS(Compare-And-Swap)操作实现的。
AQS提供了两种同步方式:独占模式和共享模式。独占模式指的是同一时间只有一个线程可以获取锁,其他线程需要等待独占锁的释放。共享模式指的是多个线程可以同时获取锁,这需要采用读写锁的机制来实现。
🍊 2. AQS的数据结构
在AQS中,同步状态和等待队列是最重要的数据结构。
🎉 (1) 同步状态
同步状态是AQS的核心,它用int类型的变量来描述同步状态。 AQS通过volatile关键字来保证同步状态的可见性,即当同步状态被修改后,所有的线程都可以立即看到最新的值。
同步状态通常用一个整数来表示,整数的值可以表示同步状态的各个属性。在独占模式下,可以使用0表示未锁定状态,1表示锁定状态。在共享模式下,可以使用高16位表示读锁的数量,低16位表示写锁的数量。通过这种方式可以保证同步状态的共享和独占模式可以共存。
🎉 (2) 等待队列
等待队列是AQS中的另一个重要数据结构,用来存储等待获取锁的线程。AQS通过一个FIFO队列来维护等待队列,队列中的每个元素代表一个等待线程。
在AQS的实现中,等待队列使用一个链表来实现。每个节点都包含前驱节点和后继节点,通过这些节点连接起来形成一个FIFO队列。加入队列的方法是通过自旋操作,不断尝试将当前节点加入到队列中。当同步状态的持有者释放锁时,它会尝试唤醒队列中的第一个线程。被唤醒的线程会再次尝试通过CAS操作获取锁,直到它成功获取锁为止。
🍊 3. AQS的锁请求和释放过程
在AQS中,当一个线程需要获取某个同步资源时,它会先尝试通过CAS操作修改同步状态,如果成功获取锁,则直接返回。获取锁的方法取决于同步资源的类型。
🎉 (1) 独占模式
如果是独占资源,那么只有一个线程可以获取锁,其他线程需要等待独占锁释放。此时,获取锁的方法是通过CAS操作修改同步状态,如果成功获取锁,则返回;否则被封装为Node节点,加入到FIFO队列中等待。
如果CAS操作失败,则说明当前线程没有成功获取锁,它就会被封装为一个Node节点,并加入到FIFO队列的尾部。当同步状态的持有者释放锁时,它会尝试唤醒队列中的第一个线程。被唤醒的线程会再次尝试通过CAS操作获取锁,直到它成功获取锁为止。
🎉 (2) 共享模式
如果是共享资源,多个线程可以同时获取锁,这就需要采用读写锁的机制。通过读锁可以实现多个线程同时对同一共享资源进行读操作,而写锁则是独占锁,只允许一个线程进行写操作。获取共享锁的方法是通过尝试通过CAS操作修改同步状态,并判断当前状态是否允许获取共享锁,如果成功获取锁,则返回;否则被封装为Node节点,加入到FIFO队列中等待。
当同步状态的持有者释放锁时,它会尝试唤醒队列中的第一个线程。被唤醒的线程会再次尝试通过CAS操作获取锁,直到它成功获取锁为止。如果获取锁的方式是共享锁,那么会唤醒队列中所有等待线程;如果获取锁的方式是独占锁,那么只会唤醒队列中的第一个线程。
🍊 4. AQS的实战使用场景
AQS是Java提供的一个同步框架,它可以用来实现锁和其他同步工具。AQS的应用非常广泛,常见的应用场景包括:
🎉 (1) ReentrantLock
ReentrantLock是一种可重入锁,它使用AQS来实现锁的功能。在ReentrantLock中,使用一个int变量来表示同步状态。当一个线程获取独占锁时,会将同步状态设置为1,当释放锁时,会将同步状态设置为0。
ReentrantLock支持多种锁模式,包括公平锁和非公平锁。公平锁是指所有等待锁的线程都按照先后顺序依次获取锁,非公平锁是指所有等待锁的线程可以竞争锁。
🎉 (2) Semaphore
Semaphore是一个计数信号量,它也使用AQS来实现。Semaphore的同步状态表示当前还有多少个许可证可用,当一个线程需要获取许可证时,它会尝试通过CAS操作获取许可证,如果成功获取许可证,则计数器减1,否则被封装为Node节点,加入到FIFO队列中等待。
🎉 (3) CountDownLatch
CountDownLatch是一个倒计时门闩,它也使用AQS来实现。CountDownLatch的同步状态表示还有多少个线程需要等待,当一个线程需要等待时,它会将同步状态减1,当同步状态为0时,所有线程都可以继续执行。
🍊 5. AQS的问题和解决方案
AQS在实际应用过程中可能会出现的问题主要有两个:饥饿和死锁。
🎉 (1) 饥饿
饥饿是指某个线程无法获取锁,导致一直处于等待状态,无法执行代码的情况。饥饿的原因有很多,例如锁竞争激烈、锁占用时间过长等。为了解决饥饿问题,可以采用公平锁的方式,保证所有线程都有机会获取锁,避免某个线程一直无法获取锁的情况。
🎉 (2) 死锁
死锁是指两个或多个线程互相持有对方所需的资源,无法继续执行的情况。死锁的原因通常是由于线程获取锁的顺序不当导致的。为了避免死锁,可以规定所有线程获取锁的顺序相同,例如都按照顺序1、2、3的方式获取锁,这样可以避免死锁的发生。
🌟 二、总结
总的来说,AQS是Java中一个非常重要的同步框架,它采用了一种非常高效的实现方式,通过CAS操作和等待队列的维护,实现了同步状态的共享和独占,并支持多种锁模式。AQS的应用非常广泛,可以用来实现ReentrantLock、Semaphore、CountDownLatch等同步工具。在实际使用过程中,需要注意饥饿和死锁问题,采用公平锁和规定获取锁的顺序等方式,可以有效避免这些问题的发生。
🔔如果您需要转载或者搬运这篇文章的话,非常欢迎您私信我哦~
希望各位读者大大多多支持用心写文章的博主,现在时代变了,信息爆炸,酒香也怕巷子深,博主真的需要大家的帮助才能在这片海洋中继续发光发热,所以,赶紧动动你的小手,点波关注❤️,点波赞👍,点波收藏⭐,甚至点波评论✍️,都是对博主最好的支持和鼓励!
- 💂 博客主页: 我是廖志伟
- 👉开源项目:java_wxid
- 🌥 哔哩哔哩:我是廖志伟
- 🎏个人社区:幕后大佬
- 🔖个人微信号:
SeniorRD
📥博主的人生感悟和目标
- 🍋程序开发这条路不能停,停下来容易被淘汰掉,吃不了自律的苦,就要受平庸的罪,持续的能力才能带来持续的自信。我本身是一个很普通程序员,放在人堆里,除了与生俱来的盛世美颜,就剩180的大高个了,就是我这样的一个人,默默写博文也有好多年了。
- 📺有句老话说的好,牛逼之前都是傻逼式的坚持,希望自己可以通过大量的作品、时间的积累、个人魅力、运气、时机,可以打造属于自己的技术影响力。
- 💥内心起伏不定,我时而激动,时而沉思。我希望自己能成为一个综合性人才,具备技术、业务和管理方面的精湛技能。我想成为产品架构路线的总设计师,团队的指挥者,技术团队的中流砥柱,企业战略和资本规划的实战专家。
- 🎉这个目标的实现需要不懈的努力和持续的成长,但我必须努力追求。因为我知道,只有成为这样的人才,我才能在职业生涯中不断前进并为企业的发展带来真正的价值。在这个不断变化的时代,我必须随时准备好迎接挑战,不断学习和探索新的领域,才能不断地向前推进。我坚信,只要我不断努力,我一定会达到自己的目标。