锁消除是指虚拟机即时编译器再运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除。
如果一段代码中,堆上的数据都不会逃逸出去从而被其他线程访问到,那就可以把它们当作栈上的数据对待,认为它们是线程私有的,同步加锁自然也就无需进行。
public String concatString(String s1, String s2, String s3) {
return s1 + s2 + s3;
}
上面的代码怎么看都跟同步没什么关系,但是由于String是一个不可变的类,对字符串的连接操作总是生成新的String对象来进行的,因此这里就存在优化的点。再JDK1.5之前,会转化成StringBuffer对象的连续append()操作,再JDK1.5及其以后的版本,会转化为StringBuilder对象的连续append()操作,即:
public String cancatString(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()方法内部。因此这里虽然有锁,但是可以被安全的消除掉,在即时编译之后,这段代码会忽略掉所有的同步而直接执行了。
网友评论