点击上方蓝字,记得关注我们!
JVM之JIT技术(四):锁粗化
引言
在上面的三篇文章中,我们首先解释了JIT的历史,JIT技术:内联、逃逸分析、锁消除等。但是,这仅仅是适用于单线程,如果需要同步,这个这些就不适合了,现在我们来介绍适用于多线程的JIT技术:锁粗化。
01
在上一篇文章中,锁消除已经简单的介绍。但是并不是所有的情况可以使用锁消除,这时我们需要使用锁粗化来提高性能。那么锁操作时怎么操作呢?这种锁粗化合并毗邻的同步代码块当两个锁使用相似的对象,因此这样可以减少同步开销。
可以看一下下面的例子:
代码一:
public void canBeMerged() {
synchronized (A.class) {
// Do something 1.
}
synchronized (A.class) {
// Do something 2.
}
synchronized (B.class) {
// Do something 3.
}
}
上面的代码可以使用锁粗化,因为连续的两个同步代码块使用了同一个对象的监视器。如果你不了解synchronized关键字,可以看这一篇文章<<Java并发之synchronized关键字>>,关于监视器的实现,可以看《Java并发之Monitor实现》。那么锁粗化后的代码怎么样呢?如下:
代码二:
public void manuallyMerged() {
synchronized (A.class) {
// Do something 1.
// Do something 2.
}
synchronized (B.class) {
// Do something 3.
}
}
这将同是对象A的监视器所监视的同步块合并,需要注意的是,我们不能合并不连续的同步块。
代码三:
public void canNotBeMerged() {
synchronized (A.class) {
// Do something 1.
}
synchronized (B.class) {
// Do something 2.
}
synchronized (A.class) {
// Do something 3.
}
}
在上面的代码中,不能使用锁粗化,因为如果合并了相同的代码块,那么将导致代码顺序紊乱,将可能导致结果错误。
02
为了更形象比较性能,我们通过JMH来测试以上三段代码的性能,如下:
可见锁粗化在很大程序上提高了程序性能。
03
不同于锁消除,锁粗化适用于并发线程的方法中,当有连续的同步代码块使用相同的对象锁,那么就可以使用锁粗化。
▼
往期精彩回顾
▼
扫描二维码
关注我们吧
你点的每个赞,我都认真当成了喜欢