【问题标题】:Java Synchronized Methods - OCPJPJava 同步方法 - OCPJP
【发布时间】:2014-07-11 03:25:30
【问题描述】:

我正在阅读一本关于 OCPJP 考试的书。它说

可以将整个方法声明为同步的。在这种情况下,当 调用声明为同步的方法,在 调用该方法的对象,当 方法返回给调用者。

我从这句话中得到了什么;

如果有一个名为 A 的类,它调用了一个同步方法,驻留在 B 类中,正在从 A 类的对象(该方法被调用)获取锁。

正确与否?

是否需要从 B 类对象获取锁?就像使用这个引用的同步块一样。

【问题讨论】:

    标签: java methods synchronization synchronized


    【解决方案1】:

    如果有一个名为 A 的类,它调用了一个同步方法, 位于 B 类中,正在从类的对象获取锁 A(方法被调用)。

    不,在这种情况下,B 类的对象将被用作锁,因为该方法属于 B 类

    【讨论】:

      【解决方案2】:

      锁在 A 使用的 B 对象上。这个对象可以在任何地方,在我的示例中它在 A 类中,但它可以通过 execute() 方法的参数传递给 A。

      想象一下:

      public class A{
          public B objectB;
      
          public void execute(){
              objectB = new B();
      
              // objectB is synchronized during the execution of the following call, no other        
              // Thread can access ANY synchronized method of objectB or any 
              // synchonized(this) block within objectB in this time
              objectB.syncedMethod();   
          }
      }
      
      public class B{
          public synchronized void syncedMethod(){
              //doImportantStuff
          }
      
          public synchronized void anotherSyncmethod(){
              //do other important stuff
          }
      }
      

      效果和方法内部的“this”同步一样(我猜生成的Java字节码会不一样,见cmets)

      public class B{
          public void syncedMethod(){
            synchronized(this){
              //doImportantStuff
            }
          }
      
          public void anotherSyncmethod(){
              synchronized(this){
               //do other important stuff
              }
          }
      }
      

      【讨论】:

      • 如果没记错的话,public synchronized ______() {...} 实际上只是public _____() {synchronized(this) {...}} 的语法糖,所以我认为它们的编译方式相同
      • 有趣的问题,我猜这是编译器的决定,因此通常无法回答。我在 Stackoverflow 上找到了这个答案:stackoverflow.com/questions/417285/…
      • 我的立场是正确的。没有意识到第一个案例会得到优化。我想知道如果方法体中有代码会发生什么......
      • 我尝试对我的示例方法使用不同的实现(但总是一次都做同样的事情)发现 synchronized(this) 版本的字节码总是长 44 个字母,类似于 stackoverflow上面回答。我在 Android Studio (0.5.8) 中使用了 javac 1.7.0_45
      • RingBuffer#isEmpty() 类上使用Java 1.8.0_05,我得到了类似的结果,除了显式synchronized(this) 的反编译字节码几乎是synchronized 版本的字节码的两倍在方法签名中。但是,(之前没有注意到这一点),synchronized 保留在方法的签名中,这意味着完全有可能是 JVM 完成了艰苦的工作,而不是编译器......而且我没有知道几乎足以弄清楚 JVM 执行什么字节码/程序集......
      【解决方案3】:

      每个对象都有一个与之关联的锁,它的所有同步方法都必须在进入方法之前获取它的锁。因此,如果任何线程在上图中描述的对象上调用 m1() 或 m2(),它必须获取包含 m1() 或 m2() 的对象上的锁,而不是自己的锁。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-10
        • 2011-09-21
        • 2011-11-08
        相关资源
        最近更新 更多