【问题标题】:How synchronized methods in abstract class works? [duplicate]抽象类中的同步方法如何工作? [复制]
【发布时间】:2018-02-19 09:02:38
【问题描述】:

我想在线程之间同步对象,这些对象扩展了一个抽象类:

public abstract class GraphicObject {

    public synchronized void test(){
        //work...
    }
}

class Circle extends GraphicObject {

}
class Rectangle extends GraphicObject {

}

考虑这个测试类:

public class Class {
     void main(){
        GraphicObject a=new Circle();
        GraphicObject b=new Rectangle();
        Runnable r1 = new MyThread(a);
        new Thread(r1).start();
        Runnable r2 = new MyThread(b);
        new Thread(r2).start();
    }

     private class MyThread implements Runnable {

       private GraphicObject g;
       public MyThread(GraphicObject g) {
          this.g=g;
       }
       public void run() {
          g.test();
       }
    }
}

在这种情况下,ab 是具有相同抽象类的独立对象。 test() 方法是否同步在一起?如果一个线程调用a.test()b.test() 锁定到所有其他线程?

我不希望,因为它们是不同的对象。

【问题讨论】:

  • 你试过编译吗?
  • 是的,但是我简化了我的代码,所以我删除了一些东西。现在我将测试类编辑为可编译,但是我的问题确实是理论上的
  • 我不太确定链接的问题是否相同。
  • 我同意:所谓的“重复”回答了一个不同的问题。我认为问题是你的标题。它似乎在问为什么你不能声明一个抽象 synchronized 方法,但你的问题的主体确实是关于抽象 中的一个具体 synchronized 方法(即,一个类也恰好声明了至少一个抽象的 other 方法。)
  • @jameslarge 你说得对,我的意思是抽象类中的同步方法...我正在编辑它

标签: java multithreading synchronization


【解决方案1】:

无法同步抽象方法。这是JLS 8.4.3:

如果包含关键字 abstract 的方法声明还包含关键字 private、static、final、native、strictfp 或 synchronized 中的任何一个,则会出现编译时错误。

覆盖抽象声明的具体方法可以同步;在这种情况下,它就像任何其他同步方法一样工作:它锁定this 实例。

【讨论】:

  • 我没有发现编译错误,我的IDE(eclipse)编译它
  • 通过您的编辑,test() 不再是一个抽象方法。您询问了抽象同步方法,但随后将您的问题编辑为不包含任何内容。
  • 好的,但现在 test() 已同步?
  • 是的——它的工作原理就像超类不是抽象的一样。该方法是同步的,这意味着它在调用该方法的每个实例的this 上同步。
【解决方案2】:

您的test() 方法已在实例上同步。因此,由于ab 是不同的实例(即使来自不同的类),它们不会相互锁定。

如果你想要这种行为,你必须使用类似的东西

synchronized (GraphicObject.class) {
    ...
}

这只能在方法实现中完成,因此没有机会从抽象父类中强制执行。

【讨论】:

    【解决方案3】:

    任何同步都绑定到调用该方法的实例。是否是抽象方法都没有关系;在您的示例中,您能够在示例中生成锁的唯一方法是从两个不同的线程调用a.test(),因为同步结束了a,而不是test()。如果它是在类上同步的静态方法,则情况会有所不同。

    【讨论】:

      【解决方案4】:

      首先,您的代码无法编译;你不能有一个带有 body 的抽象方法,一个抽象方法不能被标记为同步,尽管后者是一个 design choice

      一般来说,方法上的synchronized 关键字的作用类似于:

      methodDeclaration() {
          synchronized (this) {
            ....
          }
      }
      

      这意味着它在对象的实例上同步,这反过来意味着您示例中的这两种方法在不同的锁上同步,分别在 ab 上。

      【讨论】:

      • 好的,我没有注意到他的身体方法上的abstract。但它不会编译。
      • 我编辑代码删除了双抽象键,这是一种类型。现在它应该编译了。
      猜你喜欢
      • 2016-03-17
      • 2012-11-29
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-14
      相关资源
      最近更新 更多