原创转载请注明出处:https://agilestyle.iteye.com/blog/2443647
锁的状态
- 无锁状态
- 偏向锁状态
- 轻量级锁状态
- 重量级锁状态
锁的状态是通过对象监视器在对象头中的字段来表明的。
为了提升性能,JDK1.6引入了偏向锁、轻量级锁、重量级锁概念,来减少锁竞争带来的上下文切换,而正是新增的Java对象头实现了锁升级功能。
当Java对象呗Synchronized关键字修饰成同步锁后,围绕这个锁的一系列升级操作都将和Java对象头有关。
Java对象头
在JDK1.6的JVM中,对象实例在堆内存中被分为了三个部分:对象头、实例数据、对齐填充。其中对象头由Mark Word、指向类的指针以及数组长度三部分组成。
Mark Word记录了对象和锁有关的信息。Mark Word在64位JVM中的长度是64bit,在64位JVM的存储结构如下图所示
锁升级主要依赖于Mark Word中的锁标志位和释放偏向锁标志位,Synchronized同步锁就是从偏向锁开始的,四种状态会随着竞争的情况逐渐升级到轻量级锁,最终升级到重量级锁,而且是不可逆的过程,即不可降级。
这四种状态都不是Java语言中的锁,而是JVM在使用synchronized时为了提高锁的获取与释放效率而做的优。
偏向锁
偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。
偏向锁主要用来优化同一个线程多次申请同一个锁的竞争,在某些情况下,大部分时间是同一个线程竞争锁资源。一旦出现其他线程竞争资源时,偏向锁就会被撤销。偏向锁的撤销需要等待全局安全点,暂停持有该锁的线程,同时检查该线程是否还在执行该方法,如果是,则升级锁,反之则被其他线程抢占。
因此在高并发场景下,当大量线程同时竞争同一个锁资源时,偏向锁就会被撤销,发生STW后,开启偏向锁会带来更大的性能开销,这时可以通过添加JVM参数关闭偏向锁来调优系统性能。
-XX:-UseBiasedLocking // 关闭偏向锁(默认打开)
或
-XX:+UseHeavyMonitors // 设置重量级锁
轻量级锁
轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
轻量级锁适用于线程交替执行同步块的场景,绝大部分的锁在整个同步周期内都不存在长时间的竞争。
重量级锁
重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。
具体指轻量级锁CAS抢锁失败,线程将会被挂起进入阻塞状态。如果正在持有锁的线程在很短的时间内释放资源,那么进入阻塞状态的线程无疑又要申请锁资源。
JVM提供了一种自旋锁,可以通过自旋方式不断尝试获取锁,从而避免线程被挂起阻塞。这是基于大多数情况下,线程持有锁的时间都不会太长,毕竟线程被挂起阻塞可能会得不偿失。
JDK1.7开始,自旋锁默认启用,自旋次数由JVM设置决定,通常不建议设置的JVM重试次数过多,因为CAS重试操作意味着长时间地占用CPU。
自旋锁重试之后如果抢锁依然失败,同步锁就会升级至重量级锁。
在锁竞争不激烈且锁占用时间非常短的场景下,自旋锁可以提高系统性能。一旦锁竞争激烈或锁占用的时间过长,自旋锁将会导致大量的线程一直处于CAS重试状态,占用CPU资源,反而会增加系统性能开销。所以自旋锁和重量级锁的使用都要结合实际场景。
在高负载、高并发的场景下,可以通过设置JVM参数来关闭自旋锁,优化系统性能。
-XX:-UseSpinning // 参数关闭自旋锁优化 (默认打开) -XX:PreBlockSpin // 参数修改默认的自旋次数。JDK1.7 后,去掉此参数,由 jvm 控制
Reference
https://time.geekbang.org/column/article/101244
相关推荐
本文将详细解析Java中的偏向锁、轻量级锁和重量级锁,这些都是JVM为了提高并发性能而实现的锁优化策略。 首先,我们从最简单的偏向锁开始。**偏向锁**的设计理念是假设大多数情况下,锁都不会被多个线程竞争。当一...
当线程开始尝试获取锁时,Java会引入三种不同类型的锁:偏向锁、轻量级锁和重量级锁。 1. **偏向锁**:偏向锁是默认的锁状态,假设只有一个线程访问同步代码块,它会尝试将Mark Word中的线程ID设为当前线程ID,这样...
java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁
Java锁的升级策略是指Java语言中锁机制的四种状态:无锁状态、偏向锁、轻量级锁、重量级锁。这些锁状态都是专门针对Synchronized关键字的,是为了提高获得锁和释放锁的效率。 首先,无锁状态是指没有任何锁的状态。...
需要将锁升级到轻量级锁,在轻量级锁状态下,竞争锁的线程根据自适应自旋次数去尝试抢占锁资源,如果在轻量级锁状态下还是没有竞争到锁,就只能升级到重量级锁,在重量级锁状态下,没有竞争到锁的线程就会被阻塞,...
8. **偏向锁 / 轻量级锁 / 重量级锁** - **偏向锁** 假设锁会被同一线程多次获取,初始化时偏向某一线程,直到有其他线程尝试获取时才升级。 - **轻量级锁** 当锁被线程持有时,如果其他线程试图获取,但没有竞争...
很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,本文详细介绍了Java SE1.6中为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁,...
7. **偏向锁/轻量级锁/重量级锁** - **偏向锁**假定一个线程连续获取锁,就不再进行加锁操作,仅在多线程争抢时升级为轻量级锁。 - **轻量级锁**利用CAS操作,比重量级锁更高效,但如果锁存在竞争,会升级为重量级...
锁机制可以分为偏向锁、轻量级锁、重量级锁、自旋锁等。锁机制可以保证在多线程环境下,数据的安全和一致性。 五、Disruptor 框架 Disruptor 框架是一个高性能的并发框架,使用原子操作和锁机制来实现高效的并发...
- **分段锁/偏向锁/轻量级锁/重量级锁**:针对不同的场景优化锁性能。 - **自旋锁**:在等待锁释放时不放弃处理器时间片,而是持续尝试获取锁。 #### 常用线程池类型 - **newCachedThreadPool**:适合处理大量的...
在实际应用中,理解和掌握偏向锁、轻量级锁和重量级锁的升级过程对于优化多线程程序的性能至关重要。开发者可以根据系统的并发情况调整JVM参数,以达到更好的锁优化效果。例如,如果系统大部分时间无锁竞争,偏向锁...
偏向锁/轻量级锁/重量级锁的原理 ReentractLock synchronized与ReentractLock区别 volatile 线程池原理和参数配置 内存的多级缓存机 CAS 容器 HashMap 1.7和1.8的区别,resize过程,多线程的问题 ConcurrentHashMap ...
对象头的锁状态字段有四种可能的值,分别代表无锁状态、偏向锁、轻量级锁和重量级锁。这种设计允许锁的状态在无锁到重量级锁之间升级,但不支持降级,以提高锁的获取和释放效率。 **3. 偏向锁** 偏向锁是针对单线程...
3. **锁标志位**:当该位为1时,表示锁被升级,可能是从偏向锁升级到轻量级锁,或者是轻量级锁升级到重量级锁。 4. **对象hashCode**:在无锁状态下,这部分存储对象的哈希码。 5. **对象分代年龄**:用于垃圾收集...
2. 锁的分类:synchronized 锁可以分为轻量级锁、偏向锁和重量级锁三种。 3. 轻量级锁:轻量级锁是 synchronized 锁的一种实现方式,使用 CAS 操作来更新对象的 Mark Word。轻量级锁的加锁过程可以分为三步:创建锁...
- **实现**:synchronized基于Monitor机制,通过JVM实现,锁状态有无锁、偏向锁、轻量级锁和重量级锁四种。 - **轻量级锁**:在没有多线程竞争时,减少传统重量级锁的开销,适应线程交替执行同步块的场景。如果...
当轻量级锁的CAS操作失败,或者偏向锁发现有线程竞争时,锁会升级为重量级锁,所有等待的线程都会被挂起,直到持有锁的线程释放锁。 总结来说,Java锁的优化主要通过自旋锁、自适应自旋、锁粗化、锁衰退、偏向锁和...
这篇文档主要探讨了Java synchronized的锁机制,包括锁粗化、偏向锁、轻量级锁、重量级锁以及锁升级的过程。 1. 锁粗化: 锁粗化是编译器或运行时环境为了减少锁的使用频率,将多个连续的同步块合并成一个大的同步...
首先需要知道的是,Synchronized锁在JVM中实现了从低到高的不同锁级别,包括无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。锁的升级并不是随意进行的,而是根据锁的竞争情况逐步升级的。 偏向锁是一种优化...