锁优化
自旋锁
共享数据的锁定状态只会持续很短的一段时间,为了这段时间去挂起和恢复线程并不值得。 如果物理机器有一个以上的处理器,能让两个或以上的线程同时并行执行,我们就可以让后面请求锁的那个线程“稍等一下”,但不放弃处理器的执行时间,看看持有锁的线程是否很快就会释放锁。 为了让线程等待,我们只需让线程执行一个忙循环(自旋),这项技术就是所谓的自旋锁。 自旋等待不能代替阻塞,自旋等待本身虽然避免了线程切换的开销,但它是要占用处理器时间的,因此,如果锁被占用的时间很短,自旋等待的效果就会非常好,反之,如果锁被占用的时间很长,那么自旋的线程只会白白消耗处理器资源,而不会做任何有用的工作,反而会带来性能上的浪费。 因此,自旋等待的时间必须要有一定的限度,如果自旋超过了限定的次数仍然没有成功获得锁,就应当使用传统的方式去挂起线程了。 自旋次数的默认值是10次,用户可以使用参数-XX:PreBlockSpin来更改。
CAS是Compare And Set的缩写。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
自适应自旋
在JDK 1.6中引入了自适应的自旋锁。 自适应意味着自旋的时间不再固定了,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。 如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也很有可能再次成功,进而它将允许自旋等待持续相对更长的时间,比如100个循环。 另外,如果对于某个锁,自旋很少成功获得过,那在以后要获取这个锁时将可能省略掉自旋过程,以避免浪费处理器资源。 有了自适应自旋,随着程序运行和性能监控信息的不断完善,虚拟机对程序锁的状况预测就会越来越准确,虚拟机就会变得越来越“聪明”了。
锁消除
public String concatString(String s1,String s2,String s3){
StringBuffer sb=new StringBuffer();
sb.append(s1);
sb.append(s2);
sb.append(s3);
return sb.toString();
}
每个StringBuffer.append()方法中都有一个同步块,锁就是sb对象。 虚拟机观察变量sb,很快就会发现它的动态作用域被限制在concatString()方法内部。 也就是说,sb的所有引用永远不会“逃逸”到concatString()方法之外,其他线程无法访问到它,因此,虽然这里有锁,但是可以被安全地消除掉,在即时编 译之后,这段代码就会忽略掉所有的同步而直接执行了。
锁粗化
类似上述代码中连续的append()方法的情况, 如果虚拟机探测到有这样一串零碎的操作都对同一个对象加锁,将会把加锁同步的范围扩展(粗化)到整个操作序列的外部,以代码B为例,就是扩展到第一个append()操作之前直至最后一个append()操作之后,这样只需要加锁一次就可以了。
对象头
HotSpot虚拟机的对象头(Object Header)分为两部分信息,第一部分用于存储对象自身的运行时数据,如哈希码(HashCode)、 GC分代年龄(Generational GC Age)等,这部分数据的长度在32位和64位的虚拟机中分别为32bit和64bit,官方称它为“Mark Word”,它是实现轻量级锁和偏向锁的关键。Mark Word的32bit空间中的25bit用于存储对象哈希码(HashCode),4bit用于存储对象分代年龄,2bit用于存储锁标志位,1bit固定为0。
轻量级锁能提升程序同步性能的依据是“对于绝大部分的锁,在整个同步周期内都是不存在竞争的”,这是一个经验数据。 如果没有竞争,轻量级锁使用CAS操作避免了使用互斥量的开销,但如果存在锁竞争,除了互斥量的开销外,还额外发生了CAS操作,因此在有竞争的情况下,轻量级锁会比传统的重量级锁更慢。
轻量级锁
轻量级锁是JDK 1.6之中加入的新型锁机制,它名字中的“轻量级”是相对于使用操作系统互斥量来实现的传统锁而言的,因此传统的锁机制就称为“重量级”锁。 首先需要强调一点的是,轻量级锁并不是用来代替重量级锁的,它的本意是在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。 轻量级锁能提升程序同步性能的依据是“对于绝大部分的锁,在整个同步周期内都是不存在竞争的”,这是一个经验数据。 如果没有竞争,轻量级锁使用CAS操作避免了使用互斥量的开销,但如果存在锁竞争,除了互斥量的开销外,还额外发生了CAS操作,因此在有竞争的情况下,轻量级锁会比传统的重量级锁更慢。
偏向锁
偏向锁也是JDK 1.6中引入的一项锁优化,它的目的是消除数据在无竞争情况下的同步原语,进一步提高程序的运行性能。 如果说轻量级锁是在无竞争的情况下使用CAS操作去消除同步使用的互斥量,那偏向锁就是在无竞争的情况下把整个同步都消除掉,连CAS操作都不做了。偏向锁的“偏”,就是偏心的“偏”、 偏袒的“偏”,它的意思是这个锁会偏向于第一个获得它的线程,如果在接下来的执行过程中,该锁没有被其他的线程获取,则持有偏向锁的线程将永远不需要再进行同步。 偏向锁可以提高带有同步但无竞争的程序性能。 它同样是一个带有效益权衡(Trade Off)性质的优化,也就是说,它并不一定总是对程序运行有利,如果程序中大多数的锁总是被多个不同的线程访问,那偏向模式就是多余的。 在具体问题具体分析的前提下,有时候使用参数-XX:-UseBiasedLocking来禁止偏向锁优化反而可以提升性能。
相关推荐
《实战Java虚拟机——JVM故障诊断与性能优化》将通过200余示例详细介绍Java虚拟机中的各种参数配置、故障排查、性能监控以及性能优化。 《实战Java虚拟机——JVM故障诊断与性能优化》共11章。第1~3章介绍了Java...
《实战Java虚拟机——JVM故障诊断与性能优化》将通过200余示例详细介绍Java虚拟机中的各种参数配置、故障排查、性能监控以及性能优化。, 《实战Java虚拟机——JVM故障诊断与性能优化》共11章。第1~3章介绍了Java...
自Java 6和Java 7开始,JVM引入了多种策略来提升内部锁的效率,这些优化在server模式下运行时生效。以下是四种主要的优化方式: 1. **锁消除(Lock Elision)** 锁消除是指JIT(Just-In-Time)编译器通过逃逸分析...
JVM为了提高性能,对锁的实现进行了优化。在早期版本中,锁依赖于底层的MutexLock,这会导致线程上下文切换的开销。从JDK 1.6开始,引入了多种锁优化技术: 1. 锁粗化(Lock Coarsening):合并连续的解锁和加锁...
在JVM 8中,对锁的实现和线程同步机制进行了优化,如使用CAS(Compare and Swap)操作减少锁的开销。 7. **类型推断** 在JVM 8中,Java引入了Lambda表达式和方法引用来简化多参数匿名内部类的编写,这依赖于类型...
Java SE 7对锁和同步进行了优化,如轻量级锁和偏向锁。 9. 模块系统:Java SE 7开始引入模块系统(Project Jigsaw),虽然正式发布是在Java 9,但其设计思想在Java 7就已经开始酝酿,旨在提高代码的封装性和可维护...
- 锁优化:分析了JVM对锁的优化,如自旋锁、偏向锁和轻量级锁。 10. **实战案例** - 分布式锁:介绍如何在分布式环境中实现锁,保证多节点间的并发一致性。 - 高并发Web应用:讨论了在高并发Web应用中,如何利用...
以上内容涵盖了Java中高并发和多线程面试可能遇到的问题,包括Synchronized关键字的使用、原理、锁定对象、可重入性、JVM对锁的优化、Synchronized的公平性和非公平性、以及锁消除和锁粗化的概念。掌握这些知识点...
《实战Java虚拟机——JVM故障诊断与性能优化》将通过200余示例详细介绍Java虚拟机中的各种参数配置、故障排查、性能监控以及性能优化。, 《实战Java虚拟机——JVM故障诊断与性能优化》共11章。第1~3章介绍了Java...
《实战Java虚拟机——JVM故障诊断与性能优化》将通过200余示例详细介绍Java虚拟机中的各种参数配置、故障排查、性能监控以及性能优化。 《实战Java虚拟机——JVM故障诊断与性能优化》共11章。第1~3章介绍了Java...
HotSpot虚拟机在JDK8u262中对锁进行了诸多优化,如轻量级锁、偏向锁、自旋锁等,以减少锁的开销。源码中可以详细分析这些优化是如何实现的,以及在不同场景下的效果。 七、JVM调优工具 JDK8u262提供了如JConsole、...
Java SE7引入了Fork/Join框架,优化了并行计算,同时对锁和同步进行了改进,如轻量级锁和自旋锁。 8. **动态类型**:Java SE7引入了`钻石操作符`(`<>`),简化了匿名内部类和泛型的使用,以及`try-with-resources`...
同时,优化代码、合理设计锁策略以及使用并发工具类(如`ConcurrentHashMap`、`CountDownLatch`等)可以有效预防这类问题的发生。定期监控JVM的状态,及时发现并解决性能瓶颈,对于保持系统的稳定运行至关重要。
4. **锁的性能优化**:JVM对锁进行了多种优化,如锁消除、锁粗化、轻量级锁、偏向锁和自旋锁等。这些优化旨在减少锁带来的开销,提高并发性能。 5. **独享锁/共享锁**:在Java中,独享锁(互斥锁)通常指`...
5. 锁优化:HotSpot对锁进行了许多优化,如偏向锁、轻量级锁和重量级锁,以提升多线程环境下的性能。 通过对JDK6底层C++源码和HotSpot虚拟机源码的学习,开发者可以深入理解Java的运行机制,提高解决问题的能力,也...
因此,当一个线程首次获得锁时,会尝试对锁进行“偏见”,即标记为这个线程所有。这样一来,如果该线程后续再次尝试获取锁,就可以避免原本的锁膨胀过程,从而减少锁操作的开销。 1. **锁的状态与升级流程** 在...
- **锁优化**:JVM会对锁进行优化,比如使用偏向锁、轻量级锁等机制来提高性能。 ### 总结 在实际开发中,合理使用`synchronized`关键字对于保证程序的正确性和提高程序的并发性能至关重要。理解锁的原理、掌握锁的...
11. `Synchronized`的偏向锁、轻量级锁和重量级锁是Java内存模型对锁的优化,从低到高升级,保证线程安全。 12. `Synchronized`与`ReentrantLock`的区别在于,前者是内置锁,后者是显式锁,`ReentrantLock`提供了更...
在实际运行过程中,Java虚拟机(JVM)会对锁进行优化,包括轻量级锁、偏向锁等,这些优化是为了减少锁带来的性能开销。 - **偏向锁**:如果在一个线程中重复获取同一个锁,那么这个锁就会偏向于这个线程,其他线程...