Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 按同步方法返回值的块的同步跨度_Java_Multithreading_Synchronization - Fatal编程技术网

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

Java 按同步方法返回值的块的同步跨度,java,multithreading,synchronization,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? //

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

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.get(key)同步
  • m和m.get(key)同步
  • 在这种情况下

    synchronized (foo (m,key) ) {
      /* Critical section. */
    }
    
    …在临界区中,线程仅持有
    m.get(key)
    结果的锁线程确实获得了
    m
    的锁,但在这种情况下,它在从
    foo()返回之前被释放

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

    …在关键部分,线程只持有对
    m.get(key)
    结果的锁。线程确实获得了
    m
    的锁,但它在从
    foo()返回之前被释放。

    第二个示例同步从foo返回的对象,但不同步其他任何对象,如m。根据Java语言规范,当线程试图进入同步块时,会计算synchronized关键字后的parens表达式,结果是线程必须获取其监视器的对象

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

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

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

    第二个示例同步从foo返回的对象,但不同步其他任何对象,如m。根据Java语言规范,当线程试图进入同步块时,会计算synchronized关键字后的parens表达式,结果是线程必须获取其监视器的对象

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

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

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

    感谢您的响应。有什么参考资料我可以看一下吗?@texasbruce。我建议在实践中使用Java并发。我现在正在读这本书,到目前为止它非常棒。它很早就介绍了基本的同步,然后深入研究了其他主题。@JackmeriusTacktheritrix我将得到这本书并阅读它。谢谢你的推荐@texasbruce,Java语言规范保证在不释放锁的情况下无法退出同步块。在块的中间是否有返回语句并不重要。不管块是否抛出异常。没有释放锁就没有出路。感谢您的回复。有什么参考资料我可以看一下吗?@texasbruce。我建议在实践中使用Java并发。我现在正在读这本书,到目前为止它非常棒。它很早就介绍了基本的同步,然后深入研究了其他主题。@JackmeriusTacktheritrix我将得到这本书并阅读它。谢谢你的推荐@texasbruce,Java语言规范保证在不释放锁的情况下无法退出同步块。在块的中间是否有返回语句并不重要。不管块是否抛出异常。如果不释放锁,就没有出路了。一旦进入
    同步
    块,
    m
    上的锁已被释放,线程仅持有
    foo
    @jackmeriustacktherix结果的锁感谢您的回答!一旦您进入
    条的
    同步
    m
    上的锁已解除,线程仅持有
    foo
    @JackmeriusTacktheritrix结果的锁谢谢您的回答!感谢您的详细解释和更多示例!感谢您的详细解释和更多示例!