同步方法返回值的块同步跨度

时间:2015-10-05 17:50:32

标签: java multithreading synchronization

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

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的返回值,我想知道这些问题的答案:

  • 只有m同步?
  • 只有m.get(key)同步?
  • m和m.get(key)同步?

2 个答案:

答案 0 :(得分:7)

在这种情况下,

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

...在关键部分,线程只对m.get(key)的结果进行锁定。线程确实获得m上的锁定,但它在从foo() <返回之前被释放/ p>

答案 1 :(得分:1)

第二个例子同步foo返回的东西,但不同步其他任何东西,比如m。根据Java语言规范,当线程尝试进入同步块时,将评估synchronized关键字之后的parens中的表达式,结果是线程必须获取其监视器的对象。

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

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

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