Java 方法与成员同步

asp*_*100 0 java concurrency synchronized

我知道 java 的同步原语,当应用于方法时,在语义上等同于在方法执行期间锁定对象本身。

但是,我不清楚同时访问对象的特定成员的这个原语的契约 wrt 方法。这个原语是否只保护其他也使用它的成员之间的并发访问,或者在这个对象的任何底层成员上同步的任何成员之间的并发访问?

例如,如果同时调用下面示例中的 foo() 和 bar(),是否会导致数据竞争innerThing

class Thing {
   InnerThing innerThing;
   OtherInnerThing otherInnerThing;

   public synchronized void foo() {
      innerThing.mutate();
    }
  
  public void bar() {
      synchronized(innerThing) {
            innerThing.mutate();
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

igg*_*ggy 6

该原语仅保护其他也使用它的成员之间的并发访问,或在此对象的任何底层成员上同步的任何成员之间的并发访问。

前者。所有线程必须在同一个对象上同步。

如果线程 1 在实例上同步,并且线程 2 尝试在该实例的某个成员对象上同步,则线程 2 将不会被阻塞。

这在Java 语言规范中是隐含的;措辞谈到“同一台显示器”。

  • 正确,但值得注意的是,不存在“成员对象”这样的东西。只有两个不同的对象,一个对象被另一个对象的成员变量引用这一事实是无关紧要的。这可能是唯一的引用,这使得该对象在概念上包含在另一个中,但这是应用程序逻辑,而不是 Java 语言逻辑。JVM 此时不会检查是否有其他引用,因此该行为与跨运行时共享的对象没有什么不同,因此在概念上不包含在另一个对象中。 (2认同)