java:一个同步 vs 多个同步围绕相同的代码

java: one synchronized vs more synchronized around the same code

一个同步比很多同步好吗?

synchronized(this)
{
   CODE1
   CODE2 // uncritically code, short duration
   CODE3
   CODE4 // uncritically code, short duration
   CODE5
}

VS

synchronized(this)
{
   CODE1
}

CODE2 // uncritically code, short duration

synchronized(this)
{
   CODE3
}

CODE4 // uncritically code, short duration

synchronized(this)
{
   CODE5
}

以下内容适用:同步块尽可能小,就像我在第二个示例中编码的那样。

但这在任何情况下都是正确的吗? 如果在持续时间很短的 enoguh 中不重要的代码片段,如果我不锁定解锁锁定解锁等等,也许我的程序性能更高?

如果有助于提高性能,JVM 的优化器能够连接相邻的同步块,但它不能做相反的事情,因为拆分它会改变语义。

参见 Java SE 6 性能白皮书,2.1.2 Lock coarsening

There are some patterns of locking where a lock is released and then reacquired within a piece of code where no observable operations occur in between. The lock coarsening optimization technique implemented in hotspot eliminates the unlock and relock operations in those situations […]. It basically reduces the amount of synchronization work by enlarging an existing synchronized region.

对 Java6 的引用表明这甚至不是一个全新的功能
因此,如果您知道存在不重要的代码并且整个代码都在临时释放锁(可能会在其他线程之间更改状态),那么请使用多个同步块,告诉 JVM 和人类读者 CODE2 和CODE4 不重要。

这遵循了让运行时优化器做出正确权衡的典型模式,因为它比我们更了解实际情况,即硬件和实际应用程序行为。

您没有提供足够的信息来回答问题。

据推测,CODE1、CODE3 和 CODE5 访问与其他线程共享的数据,因为如果它们不这样做,那么使用 synchronized 就没有意义。

那么,如果线程B在线程A执行了CODE1,但还没有执行CODE3或CODE5之后,试图使用共享数据,会发生什么?如果线程 B 在线程 A 执行了 CODE1 和 CODE3 而不是 CODE5 之后尝试使用共享数据,会发生什么情况?如果结果可能发生任何不好的事情,那么您需要在 相同的 同步块中执行所有三个代码,而且,无论线程 B 正在处理相同的共享数据,它还必须在类似的 synchronized(this) 块中进行。


如果 CODE1、CODE3 和 CODE5 彼此完全独立,那么我的直觉反应是使用几个较小的 synchronized 块——尤其是如果五个 CODE 中的任何一个占用大量的时间。我喜欢让 synchronized 个块尽可能短(按时间)。

但如果性能真的很关键,那么您应该测量它并向自己证明哪种方法更好。