相关模块
通过逃逸分析后,就可进行下一步优化,锁消除 lock elision可以直接进行的优化措施。
定义
这个优化措施主要针对synchronized关键字。当JVM检测到一个锁的代码不存在多线程竞争时,会对这个对象的锁进行锁消除。
多线程并发资源竞争是一个很复杂的场景,所以要检测是否存在多线程竞争是不容易的。
但是有一个
例外,如果一个方法没有发生逃逸,那么它的内部的锁都是不存在竞争的。
代码案例展示
java
public class LockElisionTest {
public static String BufferString(String s1,String s2){
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}
public static String BuildString(String s1,String s2){
StringBuilder sb = new StringBuilder();
sb.append(s1);
sb.append(s2);
return sb.toString();
}
public static void main(String[] args) {
long start1 = System.currentTimeMillis();
for(int i=0;i<10000000;i++){
BufferString("1111111","2222222");
}
System.out.println("StringBuffer耗时:" + (System.currentTimeMillis()-start1));
long start2 = System.currentTimeMillis();
for(int i=0;i<10000000;i++){
BuildString("1111111","2222222");
}
System.out.println("StringBuild耗时:" + (System.currentTimeMillis()-start2));
}
}
关于StringBuffer和StringBuild区别说明
分别对StringBuffer和StringBuild的字符串构建方法进行了测试。这两个方法在功能上没有什么区别,最大的区别在于,StringBuffer是线程安全,对append和toString都加了synchronized同步锁,而StringBuilder没有加。synchronized关键字是在Class文件中添加了monitorenter和monitorexit两个字节码指令的,所以,StringBuffer比StringBuild更慢。
案例分析
开启JVM锁消除
在当前代码中,BufferString方法只是在main这一个线程里调用 ,不存在线程竞争,所有这个synchronized同步锁是没有作用的,因此,触发JIT后,JVM会在编绎时对这个无用的锁进行消除。这样,两个方法的耗时是差不多。
StringBuffer耗时:279
StringBuild耗时:192
关闭锁消除
通过设置JVM参数:-XX:-EliminateLocks 主动关闭锁消除后,再执行这个案例,就能明显看出差距了
StringBuffer耗时:1013
StringBuild耗时:107