抽象类中的同步方法如何工作?

时间:2017-09-11 07:26:27

标签: java multithreading synchronization

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

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()锁定到所有其他线程?

我期待不,因为它们是不同的对象。

4 个答案:

答案 0 :(得分:4)

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

  

如果包含关键字abstract的方法声明还包含private,static,final,native,strictfp或synchronized中的任何一个关键字,那么这是一个编译时错误。

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

答案 1 :(得分:2)

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

如果您想要这种行为,则必须使用类似

的内容
synchronized (GraphicObject.class) {
    ...
}

并且只能在方法实现中完成,所以没有机会从抽象父类强制执行它。

答案 2 :(得分:1)

首先,你的代码不会编译;你不能使用body的抽象方法,并且抽象方法不能被标记为已同步,尽管后者是design choice

一般来说,y关键字方法的工作原理如下:

widget

这意味着它在一个对象的实例上同步,这反过来意味着您的示例中的这两个方法分别在synchronizedmethodDeclaration() { synchronized (this) { .... } } 上的另一个锁上同步。

答案 3 :(得分:1)

任何同步都绑定到调用该方法的实例。它是否是抽象方法并不重要;在您的示例中,您可以在示例中生成锁定的唯一方法是从两个不同的线程调用a.test(),因为同步已超过a,而不是test()。如果它是一个在类上同步的静态方法,则会有所不同。