0

我想要一个同步块,其中要同步的对象是从方法调用返回的:

...
synchronized( someGetMethod() ) {
// synchronized block
}
...

是否假设“someGetMethod”已同步或仅“//同步块”部分?

先感谢您

编辑:我有一个集合(要锁定的对象映射)。“someGetMethod”检查对象是否存在于地图上,如果没有,它将添加并返回它以便被锁定。从下面的答案中,我了解到“someGetMethod”可以返回一个已经在 Map 上的值,但是在进入同步块之前,切换到另一个线程,这可能会删除上述值。结果,另一个线程可能通过“someGetMethod”进行相同的检查,现在得到不同的结果。所以看来我应该从同步块中删除,有更好的选择吗?

Edit2:谢谢大家的帮助。我发现了一个类似的问题 - Java synchronized block using method call to get synch object

4

2 回答 2

3

这:

synchronized( someGetMethod() ) {
// synchronized block
}

是相同的

Object obj = someGetMethod();
synchronized( obj ) {
// synchronized block
}

所以不,someGetMethod()不是以同步方式调用的。

如果你希望它被同步,你要么必须声明方法同步,要么显式同步,例如:

synchronized (this) {
  synchronized( someGetMethod() ) {
    // synchronized block
  }
}
于 2019-10-06T10:17:15.487 回答
2

someGetMethod()是一个表达式,它在与表达式的结果相关联的监视器被线程锁定之前进行评估。

14.19。同步声明

通过首先评估表达式来执行同步语句。然后:

  • 如果 Expression 的评估由于某种原因突然完成,则同步语句由于相同的原因而突然完成。

  • 否则,如果 Expression 的值为 null,则会引发 NullPointerException。

  • 否则,令Expression的非空值为V。执行线程锁定与V关联的监视器。然后执行Block,然后有一个选择:

    • 如果块的执行正常完成,则监视器被解锁并且同步语句正常完成。

    • 如果 Block 的执行由于任何原因突然完成,则监视器被解锁并且同步语句由于同样的原因突然完成。

您不能输入同步块、评估表达式,然后查看与结果关联的监视器。您是如何在不评估其表达式的情况下进入该块的?你用什么显示器来同步someGetMethod()自己?

于 2019-10-06T10:18:56.227 回答