通过同步方法 return 值对块进行同步跨度

synchronized span for block by synchronized method return value

我有一个如下所示的同步方法:

static Object foo (Map m, String key) {
  synchronized (m) {
    //...
    return m.get(key);
  }
}

和另一个调用此方法的方法:

static void bar (Map m, Stirng key) {
  synchronized (foo (m,key) ) {
    //Is m still synchronized locked here?
    //...
  }
}

我的问题如上。由于synchronized块在foo的return值上,我想知道这些问题的答案:

在这种情况下,

synchronized (foo (m,key) ) {
  /* Critical section. */
}

…在临界区,线程只对m.get(key)的结果持有锁线程确实获得了m上的锁,但是在从[=13=返回之前被释放了]

第二个示例对从 foo 返回的事物进行同步,但不对其他任何事物进行同步,例如 m。根据Java Language Spec,当一个线程试图进入一个synchronized块时,synchronized关键字后面括号中的表达式被计算,结果是线程必须获取其监视器的对象。

同步取决于共享锁,如果您的方法不共享同一个锁,那么它将无法工作。如果您还需要代码来获取 m 上的锁,您可以执行类似

的操作
static void bar(Map m, String key) {
    synchronized (m) {
        synchronized (foo (m,key) ) {
            //...
        }
    }
}

因为内在锁是可重入的(在外部块中获取锁不会阻止 foo 再次获取它)。