JVM 级别的锁机制的优化主要针对这两种情况:
1> 大多数情况不会存在竞争的锁.
2> 被频繁竞争的锁.
以下采用事例的方式加以说明. 前三种方法是针对情况1>, 最后一种是针对情况2>.
1. lock elision
public String getStoogeNames() {
Vector v = new Vector();
v.add("Moe");
v.add("Larry");
v.add("Curly");
return v.toString();
}
我们知道Vector的实现是线程安全的,也就是加了synchronized. 但是在上面的这段代码中, 显然Vector v 不会被其他的线程所共享. 这个时候Vector实现中的锁是可以完全去掉的. 这种情况下, java 在compile的时候就能根据变量的作用域来进行相应的优化.比如:在生成的bytecode中去除掉所有的lock,unlock逻辑.
2. Biased Locking
public void getStoogeNames(Vector v) {
String[] names = {"Moe", "Larry", "Curly"};
for (int i=0; i<names.length; i++)
{
v.add(names[i]);
}
}
请注意代码中的循环. 由于Vector v 这里非局部变量, 所以compiler不会对这段代码进行第一种优化. 这时, 一般情况下, 在每次循环进入v.add()时会做lock处理, 在退出时做unlock处理. 但是, 如果假设Vector v 在大多数情况下都只会被单个线程所占用, 那么JVM可以做这样的处理: 当前占有该锁的线程只在有其他线程请求到来时才进行解锁操作, 从而降低当前线程再次获得锁的overhead.
显然, 要做这种处理, JVM需要先动态的得到统计数据表明该锁将在大部分时间内被单个线程占用.
3. Lock coarsening
public void addStooges(Vector v) {
v.add("Moe");
v.add("Larry");
v.add("Curly");
}
这个问题其实和例2差不多. 这里就不赘述. 这次我们采用另一种方法: 将所有的add操作
并入一个lock-unlock块中, 也就是所谓的粗化锁粒度.
其实也可以用这种方式来处理方法2种的例子. 但是他们的不同是, 这种方法可能会导致其他线程长时间的得不到锁, 因为这种方式可能会产生出非常长的一段critical section, 系统总的吞吐量从而降低.
4. Adaptive lock
这是这里面唯一的一种处理被多线程频繁访问的锁的. 在这种情况下一般有两种竞争锁的方式:
1> 当某个线程未能得到锁时, 它将不断的询问(spin lock), 如下例所示:
while (lockStillInUse)
;
这种方式的优点是: 当临界段的处理很快时会有很快得到响应. 缺点是:会大量占用cpu资源.
2> 当某线程未能得到锁时, 将其挂起, 并等待重新调度(suspension lock)
这种方式刚好和方式1>互补.
那么既然如此, 为什么不同时利用这两种方法的优点呢?
这就是adaptive lock要做的事. JVM 可以先尝试着用spin lock, 如果发现线程都能在这种方式下很快的获得锁,那么就继续使用它. 如果发现超过了特定的时间线程还是未能得到锁则切换到suspension lock. 像这样经过一段时间的探索, JVM就可确定使用哪种方式.
好了, 这是我对JVM级别锁优化的认识. 欢迎大家和我讨论.
参考文献:
[1] Java SE 6 Performance White Paper
http://java.sun.com/performance/reference/whitepapers/6_performance.html#2.1.2
[2] Java theory and practice: Synchronization optimizations in Mustang
http://www.ibm.com/developerworks/java/library/j-jtp10185/index.html
[3] Java Synchronization Optimizations
http://blogs.sun.com/dagastine/entry/java_synchronization_optimizations_in_mustang
[4] Eliminating Synchronization-Related Atomic Operations with Biased Locking and Bulk Rebiasing
http://java.sun.com/javase/technologies/hotspot/publications/biasedlocking_oopsla2006_wp.pdf
分享到:
相关推荐
通过以上对Java锁机制的详细介绍,可以看出Java在并发控制方面具有丰富的工具和策略,它们能够帮助开发者在多线程编程中处理好资源竞争和线程协作的问题,从而编写出高效且线程安全的应用程序。
Java锁机制是Java多线程编程中的核心概念之一,其主要目的是确保在多线程环境下,多个线程能够安全地访问共享资源,避免数据不一致的问题。Java锁机制的发展历经了多个版本的改进,尤其是Java 5.0引入的显示锁...
"面向Java锁机制的字节码自动重构框架"可能是一种工具或库,它允许开发者通过字节码操作自动地对Java代码进行锁优化。这样的框架可能会分析现有的代码,识别出可以优化的锁,并自动插入适当的显式锁替换内置锁,或者...
5. 重量级锁:重量级锁是 synchronized 锁的一种实现方式,使用互斥量来实现锁机制。 二、ReentrantLock 锁 1. 锁的原理:ReentrantLock 锁是基于 AQS(AbstractQueuedSynchronizer)机制来实现的。 2. 锁的分类:...
Java锁机制是多线程编程中的核心概念,用于控制对共享资源的并发访问,防止数据的不一致性。Java提供了多种锁机制,包括内置锁(也称为监视器锁)和显式锁。本文将详细解析Java锁机制及其应用。 1. **内置锁(监视...
本文提到的基于硬件cache锁机制的Java虚拟机即时编译器优化,意味着在即时编译的过程中,JVM尝试利用CPU的硬件cache锁功能来优化编译后代码的执行。这种优化策略可能涉及动态地锁住涉及频繁访问数据的缓存行,或是在...
根据提供的文件信息,我们可以推断出这是一本关于Java程序性能优化的书籍,作者是葛一鸣,并提供了该书PDF版本的下载链接。虽然没有具体的书籍内容,但基于标题、描述以及通常这类书籍会涉及的主题,我们可以总结出...
在Java编程中,线程的等待唤醒机制是多线程编程中的重要概念,它涉及到如何有效地协调多个线程之间的交互,以确保程序的正确运行。本文将深入探讨这个主题,并提供一些代码优化的建议,适合Java初学者进行学习和参考...
"Java虚拟机中的动态锁cache优化" Java虚拟机(JVM)是Java语言的运行环境,它提供了一个在不同平台上运行Java程序的通用平台。为提高Java程序的执行效率,JVM使用即时编译器(Just-In-Time compiler,JIT)来编译...
本文将详细介绍Java锁的膨胀过程和优化策略。 首先,我们来看自旋锁。自旋锁是一种优化策略,当一个线程尝试获取已被其他线程持有的锁时,它并不会立即阻塞,而是会进行一次忙循环,持续检查锁是否已释放。如果持有...
Java虚拟机(JVM)中的锁机制是实现多线程共享数据结构同步的关键机制。锁机制维护的临界区域通常对共享数据结构只进行读操作。只读锁是指当某个线程持有锁在只读临界区域时,其他线程可以直接进入只读临界区域而...
3. **并发与多线程**:掌握线程池的使用,理解synchronized、volatile、Lock等并发控制机制,以及如何减少锁的争用和死锁问题。 4. **数据结构与算法**:根据具体场景选择合适的数据结构,如HashMap、TreeMap、...
- 优化锁机制:减少锁竞争,使用读写锁(ReadWriteLock)进行优化,或者使用CAS(Compare-And-Swap)实现无锁编程。 #### JVM参数调优 - 设置JVM最大内存和初始内存,合理使用-Xms和-Xmx参数。 - 设置垃圾收集器...
5.2 锁机制对比 5.3 增加程序并行性 5.4 JDK类库使用 5.5 本章小结 第6章 JVM性能测试及监控 6.1 监控计算机设备层 6.2 监控JVM活动 6.3 本章小结 第7章 JVM性能调优建议 7.1 JVM相关概念 7.2 JVM系统架构...
- **多线程优化**:合理使用线程池,避免大量创建和销毁线程,使用synchronized代替锁来降低上下文切换的开销。 3. **性能测试与调优** - **性能测试工具**:利用JProfiler、VisualVM等工具进行性能监控,找出...
在Java编程领域,程序性能优化是一项至关重要的任务,它直接影响到软件的运行效率、资源消耗以及用户体验。"Java程序性能优化"这个主题涵盖了多种技术与策略,旨在提升Java应用程序的运行速度,减少内存占用,以及...
Java并发机制的底层实现原理涉及到多个方面,包括了本地内存与...Java虚拟机通过一系列的优化和机制保证了并发环境下的数据一致性与程序的正确执行。这些机制共同作用,保证了Java程序在多线程环境下的健壮性和可靠性。