很多人习惯把线程安全的StringBuffer用做局部变量,依赖于JIT,不比StringBuilder慢。
StringBuffer虽然加了synchronized,做局部变量时,锁住的只是线程局部变量,没有锁竞争
类似于synchronized(new Object()),是没有意义的。
JVM运行一会就发现这个无意义的锁,可以被清除掉,就做“锁省略”优化.
再执行,无锁的StringBuffer性能就跟StringBuilder差不多了.
这个简单的近乎没有意义的测试(或者因为如此吧,被投了几个“新手贴”, 哈。。。),测的却是表面上看不到的优化
参考
JVM优化之逃逸分析(Escape Analysis) http://www.iteye.com/topic/473355
Mustang 中的同步优化 http://www.ibm.com/developerworks/cn/java/j-jtp10185/
再谈 Urban 性能传言 http://www.ibm.com/developerworks/cn/java/j-jtp09275.html
public void test() throws Exception {
int total = 11000000;
for (int x = 0; x < 100; x++) {
StringBuffer sb1 = new StringBuffer(total);
long start = System.currentTimeMillis();
for (int i = 0; i < total; i++) {
sb1.append(1);
}
long sb1Time = System.currentTimeMillis() - start;
StringBuilder sb2 = new StringBuilder(total);
start = System.currentTimeMillis();
for (int i = 0; i < total; i++) {
sb2.append(1);
}
System.out.println(sb1Time + " " + (System.currentTimeMillis() - start));
}
}
执行结果
688 203
688 219
688 219
703 203
687 203
218 218
218 218
218 203
219 219
219 219
219 203
.......
可以看到,前几次调用,StringBuffer比StringBuilder慢的多,执行几次之后,两者已经接近
分享到:
评论
There is a lock associated with every object. The Java programming language does not provide a way to perform separate lock and unlock operations; instead, they are implicitly performed by high-level constructs that always arrange to pair such operations correctly. (The Java virtual machine, however, provides separate monitorenter and monitorexit instructions that implement the lock and unlock operations.)
<div class="quote_div">
<p> </p>
<p style="margin: 0px;">这个简单的近乎没有意义的测试(或者因为如此吧,被投了几个“新手贴”, 哈。。。)</p>
<p> </p>
</div>
<p> </p>
<p>就是说,你明知道是新手帖,还不往入门版发喽</p>
无语。。。
这里测的不是多线程的锁竞争,而是要看出JIT的运行时编译优化,锁省略优化
诸如循环展开,方法内联等编译优化。
呵呵·是我考虑不周。我研究一下
Enables a technique for improving the performance of uncontended synchronization. An object is "biased" toward the thread which first acquires its monitor via a monitorenter bytecode or synchronized method invocation; subsequent monitor-related operations performed by that thread are relatively much faster on multiprocessor machines. Some applications with significant amounts of uncontended synchronization may attain significant speedups with this flag enabled; some applications with certain patterns of locking may see slowdowns, though attempts have been made to minimize the negative impact.
注: java5.0 下, 这个参数是关闭的。
虽然JIT 优化了非竞争同步, 但是, 程序员们不要依赖这个特定优化。 我相信JIT未必能100%做到这个事情。 特别是一些读共享的代码。 JIT就未必能意识到是不是需要同步。
这个优化对于一些老代码的的确非常有效, 我做过不少测试, 几乎是性能毫无下降。 但是新代码, 不需要使用同步的代码, 尽量不要。
当然用StringBuilder是更好的,但因为编译期优化的存在,也可以不用把老代码中的StringBuffer替换回来。
执行几次之后,JIT就会优化成跟StringBuilder接近的性能。
无语。。。
这里测的不是多线程的锁竞争,而是要看出JIT的运行时编译优化,锁省略优化
诸如循环展开,方法内联等编译优化。
请了解一下JIT再来看是不是猜的吧
jvm 可以自动释放锁的啊?