Evg*_*eev 18 java concurrency synchronization
这之间的表现有什么不同吗?
synchronized void x() {
y();
}
synchronized void y() {
}
Run Code Online (Sandbox Code Playgroud)
还有这个
synchronized void x() {
y();
}
void y() {
}
Run Code Online (Sandbox Code Playgroud)
chr*_*ke- 16
是的,还有一个额外的性能成本,除非并且直到JVM内联调用y()
,现代JIT编译器将以相当短的顺序执行调用.首先,考虑一下你y()
在课堂外可见的情况.在这种情况下,JVM必须检查进入y()
以确保它可以进入对象上的监视器; 当呼叫来自时,此检查将始终成功x()
,但不能跳过,因为呼叫可能来自课外的客户端.这项额外的检查费用很低.
此外,考虑其中的情况y()
是private
.在这种情况下,编译器仍然不会优化同步 ; 看下面一个空的反汇编y()
:
private synchronized void y();
flags: ACC_PRIVATE, ACC_SYNCHRONIZED
Code:
stack=0, locals=1, args_size=1
0: return
Run Code Online (Sandbox Code Playgroud)
根据规范的定义synchronized
,每个进入synchronized
块或方法的入口都对对象执行锁定操作,并且离开执行解锁操作.在锁定计数器降至零之前,没有其他线程可以获取该对象的监视器.据推测,某种静态分析可以证明private synchronized
方法只能从其他synchronized
方法中调用,但Java的多源文件支持最多会使脆弱,甚至忽略反射.这意味着JVM必须在输入时增加计数器y()
:
调用
synchronized
方法的监视条目,并在其返回时监视退出,由Java虚拟机的方法调用和返回指令隐式处理,就像使用了monitorenter和monitorexit一样.
@AmolSonawane正确地指出,JVM可以在运行时通过执行锁定粗化来优化此代码,实质上是内联y()
方法.在这种情况下,JVM已经决定执行JIT优化后,要求从x()
以y()
不会产生任何额外的性能开销,当然直接调用y()
从任何其他位置仍然需要单独购买显示器.
Benchmark Mean Mean error Units
c.a.p.SO18996783.syncOnce 21.003 0.091 nsec/op
c.a.p.SO18996783.syncTwice 20.937 0.108 nsec/op
Run Code Online (Sandbox Code Playgroud)
=>无统计学差异.
查看生成的程序集显示已执行锁定粗化,并且虽然已同步y_sync
,x_sync
但已内联.
完整结果:
Benchmarks:
# Running: com.assylias.performance.SO18996783.syncOnce
Iteration 1 (5000ms in 1 thread): 21.049 nsec/op
Iteration 2 (5000ms in 1 thread): 21.052 nsec/op
Iteration 3 (5000ms in 1 thread): 20.959 nsec/op
Iteration 4 (5000ms in 1 thread): 20.977 nsec/op
Iteration 5 (5000ms in 1 thread): 20.977 nsec/op
Run result "syncOnce": 21.003 ±(95%) 0.055 ±(99%) 0.091 nsec/op
Run statistics "syncOnce": min = 20.959, avg = 21.003, max = 21.052, stdev = 0.044
Run confidence intervals "syncOnce": 95% [20.948, 21.058], 99% [20.912, 21.094]
Benchmarks:
com.assylias.performance.SO18996783.syncTwice
Iteration 1 (5000ms in 1 thread): 21.006 nsec/op
Iteration 2 (5000ms in 1 thread): 20.954 nsec/op
Iteration 3 (5000ms in 1 thread): 20.953 nsec/op
Iteration 4 (5000ms in 1 thread): 20.869 nsec/op
Iteration 5 (5000ms in 1 thread): 20.903 nsec/op
Run result "syncTwice": 20.937 ±(95%) 0.065 ±(99%) 0.108 nsec/op
Run statistics "syncTwice": min = 20.869, avg = 20.937, max = 21.006, stdev = 0.052
Run confidence intervals "syncTwice": 95% [20.872, 21.002], 99% [20.829, 21.045]
Run Code Online (Sandbox Code Playgroud)