Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java 并发编程:AQS 的自旋锁

Java 并发编程:AQS 的自旋锁

原创
作者头像
码农架构
修改于 2020-12-24 10:21:16
修改于 2020-12-24 10:21:16
1.7K0
举报
文章被收录于专栏:码农架构码农架构

互斥锁在AQS的互斥锁与共享锁中已经做了详细介绍,一个锁一次只能由一个线程持有,其它线程则无法获得,除非已持有锁的线程释放了该锁。这里为什么提互斥锁呢?其实互斥锁和自旋锁都是实现同步的方案,最终实现的效果都是相同的,但它们对未获得锁的线程的处理方式却是不同的。对于互斥锁,当某个线程占有锁后,另外一个线程将进入阻塞状态。与互斥锁类似,自旋锁保证了公共数据在任意时刻最多只能由一条线程获取使用,不同的是在获取锁失败后自旋锁会采取自旋的处理方式。

自旋锁

自旋锁是一种非阻塞锁,它的核心机制就在自旋两个字,即用自旋操作来替代阻塞操作。某一线程尝试获取某个锁时,如果该锁已经被另一个线程占用的话,则此线程将不断循环检查该锁是否被释放,而不是让此线程挂起或睡眠。一旦另外一个线程释放该锁后,此线程便能获得该锁。自旋是一种忙等待状态,过程中会一直消耗CPU的时间片。

为什么自旋

互斥锁有一个很大的缺点,即获取锁失败后线程会进入睡眠或阻塞状态,这个过程会涉及到用户态到内核态的调度,上下文切换的开销比较大。假如某个锁的锁定时间很短,此时如果锁获取失败则让它睡眠或阻塞的话则有点得不偿失,因为这种开销可能比自旋的开销更大。总结起来就是互斥锁更适合持有锁时间长的情况,而自旋锁更适合持有锁时间短的情况。

自旋锁特点

  • 自旋锁的核心机制就是死等,所有想要获得锁的线程都在不停尝试去获取锁,当然这也会引来竞争问题。
  • 与互斥锁一样,自旋锁也只允许一个线程获得锁。
  • 自旋锁能提供中断机制,因为它并不会进入阻塞状态,所以能很好支持中断。
  • 自旋锁适用于锁持有时间叫短的场景,即锁保护临界区很小的常见,这个很容易理解,如果持有锁太久,那么将可能导致大量线程都在自旋,浪费大量CPU资源。
  • 自旋锁无法保证公平性,不保证先到先获得锁,这样就可能造成线程饥饿。
  • 自旋锁需要保证各个本地缓存数据的一致性,在多处理器机器上,每个线程对应的处理器都对同一个变量进行读写。每次写操作都需要同步每个处理器缓存,这可能会影响性能。

自旋锁例子

下面看一个简单的自旋锁的实现,主要看lock和unlock两个方法,Unsafe仅仅是为操作提供了硬件级别的原子CAS操作。对于lock方法,假如有若干线程竞争,能成功通过CAS操作修改value值为newV的线程即是成功获取锁的线程。它将顺利通过,而其它线程则不断在循环检测value值是否改回0,将value改为0的操作就是获取锁的线程执行完后对该锁进行释放。对于unlock方法,用于释放锁,释放后若干线程又继续对该锁竞争。如此一来,没获得锁的线程也不会被挂起或阻塞,而是不断循环检查状态。

AQS的自旋机制

AQS框架中不管是互斥锁还是共享锁实现的基础思想都是基于自旋的机制,不过它对自旋锁做了优化,这个后面会继续讲解。比如下面两图为AQS框架获取独占锁和共享锁的逻辑,具体的逻辑我们先不用管,主要关注方框框住的for(;;)这行代码。这便是自旋操作,通过无限循环来实现自旋

技术号:码农架构

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
面试官:你说说互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景
但生活中也不是没有 BUG 的,比如加锁的电动车在「广西 - 窃·格瓦拉」面前,锁就是形同虚设,只要他愿意,他就可以轻轻松松地把你电动车给「顺走」,不然打工怎么会是他这辈子不可能的事情呢?牛逼之人,必有牛逼之处。
小林coding
2020/09/18
3.2K1
【JUC进阶】07. 自旋锁
从JDK6版本开始,HotSpot虚拟机开发团队就花费了大量的资源来实现各种的锁优化技术,前面介绍到的轻量级锁(Lightweight Locking)、偏向锁(Biased Locking)就是其中的两种方式,而今天要讲的自旋锁(Adaptive Spinning)也是为了在线程之间更高效地共享数据及解决竞争问题,从而提高程序的执行效率。
有一只柴犬
2024/01/25
1600
【JUC进阶】07. 自旋锁
偏向锁、轻量级锁、重量级锁、自旋锁、自适应自旋锁
偏向锁就是在运行过程中,对象的锁偏向某个线程。即在开启偏向锁机制的情况下,某个线程获得锁,当该线程下次再想要获得锁时,不需要重新申请获得锁(即忽略synchronized关键词),直接就可以执行同步代码,比较适合竞争较少的情况。
一个会写诗的程序员
2020/05/26
4.9K0
自旋锁
讲自旋锁之前了解互斥锁 一个锁一次只能由一个线程持有,其它线程则无法获得,除非已持有锁的线程释放了该锁。
赵哥窟
2022/06/01
8320
如何使用C++11原子操作实现自旋锁
C++自旋锁是一种低层次的同步原语,用于保护共享资源的访问。自旋锁是一种轻量级的锁,适用于短时间的资源锁定。
音视频牛哥
2023/09/02
8020
如何使用C++11原子操作实现自旋锁
嵌入式Linux:线程同步(自旋锁)
Linux 自旋锁(spinlock)是一种用于保护共享资源的锁机制,常用于多核处理器中,在某个核(或线程)试图获取锁时,如果发现锁已被其他核持有,它会忙等(不断循环检查)而不是让出 CPU 时间片。
不脱发的程序猿
2025/03/17
1750
嵌入式Linux:线程同步(自旋锁)
Java中15种锁的介绍
在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类。介绍的内容如下:
Java团长
2019/04/25
3990
018.多线程-悲观锁、乐观锁、重入锁、读写锁、自旋锁、CAS无锁机制
顾名思义,就是很悲观。每次去拿数据的时候都认为别人会修改,所以都会上锁。这样别人想拿这个数据就会阻塞(block)直到它拿到锁。传统的关系型数据库里面就用到了很多这种锁机制。比如:行锁,表锁,读锁,写锁等,都是在做操作之前先上锁。
qubianzhong
2018/11/21
2K0
看完你就明白的锁系列之自旋锁
在上一篇文章 看完你就应该能明白的悲观锁和乐观锁 中我们已经学习到了什么是悲观锁和乐观锁、悲观锁和乐观锁的实现、优缺点分别是什么。其中乐观锁的实现之一 CAS 算法中提到了一个自旋锁的概念,为了全面理解 CAS 算法就首先需要了解一下自旋锁 是什么,自旋锁的适用场景和优缺点分别是什么,别着急,下面为你一一列举。
cxuan
2019/10/11
1.2K0
看完你就明白的锁系列之自旋锁
自旋锁:原理、实现与应用
自旋锁的核心思想是通过一个共享变量(通常是原子变量)来控制锁的状态。当一个线程尝试获取锁时,它会检查该变量的值:
用户11396661
2025/02/17
1670
Java并发编程之AQS以及源码解析
AQS(AbstractQueuedSynchronizer)是 Doug Lea 大师创作的用来构建锁或者其他同步组件(信号量、事件等)的基础框架类。
Java技术债务
2022/09/26
6940
Java并发编程之AQS以及源码解析
乐观锁&悲观锁&自旋锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
代码宇宙
2023/02/16
1K0
Java并发编程:AQS对CLH锁的优化
自旋锁适用于锁占用时间短,即锁保护临界区很小的情景<AQS的自旋锁详解>。它需要保证各缓存数据的一致性,这可能会导致性能问题。因为在多处理器机器上每个线程对应的处理器都对同一个变量进行读写,而每次读写都要同步每个处理器的缓存。此外,自旋锁无法保证公平性,即不保证先到先获得,这就可能造成线程饥饿。
码农架构
2021/01/12
8760
Java并发编程:AQS对CLH锁的优化
图森未来面试官:Java并发中,自旋锁如何实现同步?
我们知道自旋锁是实现同步的一种方案,它是一种非阻塞锁。它与常规锁的主要区别就在于获取锁失败后的处理方式不同,常规锁会将线程阻塞并在适当时唤醒它。而自旋锁的核心机制就在自旋两个字,即用自旋操作来替代阻塞操作。某一线程尝试获取某个锁时,如果该锁已经被另一个线程占用的话,则此线程将不断循环检查该锁是否被释放,而不是让此线程挂起或睡眠。一旦另外一个线程释放该锁后,此线程便能获得该锁。自旋是一种忙等待状态,过程中会一直消耗CPU的时间片。
Java程序猿
2021/08/09
5400
【Linux】:多线程(读写锁 && 自旋锁)
🔥 读写锁(Read-Write Lock)是一种用于多线程环境下同步访问共享资源的锁。它与传统的互斥锁(Mutex)有所不同,提供了更细粒度的控制,以便提高并发性能。它允许多个线程同时 读取 数据,但在写入数据时,必须确保只有一个线程可以进行写操作,并且在写操作期间,所有的读操作都必须等待。
IsLand1314
2024/12/20
4430
【Linux】:多线程(读写锁 && 自旋锁)
Java 中的锁 (总结)
像 乐观锁,悲观锁,互斥锁 等也都是 并发控制的机制,或者说是资源争用控制的机制。
张云飞Vir
2021/07/19
5350
Java 中的锁 (总结)
面试必备之深入理解自旋锁
分享一个我自己总结的Java学习的系统知识点以及面试问题,目前已经开源,会一直完善下去,欢迎建议和指导欢迎Star: https://github.com/Snailclimb/Java-Guide
用户2164320
2018/07/27
5.7K0
面试必备之深入理解自旋锁
Java 种15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁等等
在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类。介绍的内容如下:
美的让人心动
2019/06/15
2.5K0
不可不说的Java“锁”事
Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自JDK 8)、使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。
美团技术团队
2018/11/16
7660
可重入锁的意思上边这个代码 a b都用到锁 执行b的时候不会因为a获取锁后还没释放而无法获得锁不能执行代码 a获得锁后 执行b后不用再获取锁 直接执行就可以
周杰伦本人
2022/10/25
2830
相关推荐
面试官:你说说互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档