从同步方法调用同步方法的同步成本是多少?

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虚拟机的方法调用和返回指令隐式处理,就像使用了monitorentermonitorexit一样.

@AmolSonawane正确地指出,JVM可以在运行时通过执行锁定粗化来优化此代码,实质上是内联y()方法.在这种情况下,JVM已经决定执行JIT优化后,要求x()y()不会产生任何额外的性能开销,当然直接调用y()从任何其他位置仍然需要单独购买显示器.

  • 为什么不在答案中发布详细解释? (4认同)

ass*_*ias 8

使用jmh运行微基准测试的结果

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)