我想在线程之间同步对象,这些对象扩展了一个抽象类:
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();
}
}
}
在这种情况下,a
和b
是具有相同抽象类的独立对象。 test()
方法是否同步在一起?如果一个线程调用a.test()
被b.test()
锁定到所有其他线程?
我期待不,因为它们是不同的对象。
答案 0 :(得分:4)
无法同步抽象方法。这是JLS 8.4.3:
如果包含关键字abstract的方法声明还包含private,static,final,native,strictfp或synchronized中的任何一个关键字,那么这是一个编译时错误。
可以同步覆盖抽象声明的具体方法;在这种情况下,它就像任何其他同步方法一样工作:它锁定this
实例。
答案 1 :(得分:2)
您的test()
方法已在实例上同步。因此,a
和b
是不同的实例(即使是来自不同的类),它们也不会相互锁定。
如果您想要这种行为,则必须使用类似
的内容synchronized (GraphicObject.class) {
...
}
并且只能在方法实现中完成,所以没有机会从抽象父类强制执行它。
答案 2 :(得分:1)
首先,你的代码不会编译;你不能使用body的抽象方法,并且抽象方法不能被标记为已同步,尽管后者是design choice。
一般来说,y
关键字方法的工作原理如下:
widget
这意味着它在一个对象的实例上同步,这反过来意味着您的示例中的这两个方法分别在synchronized
或methodDeclaration() {
synchronized (this) {
....
}
}
上的另一个锁上同步。
答案 3 :(得分:1)
任何同步都绑定到调用该方法的实例。它是否是抽象方法并不重要;在您的示例中,您可以在示例中生成锁定的唯一方法是从两个不同的线程调用a.test()
,因为同步已超过a
,而不是test()
。如果它是一个在类上同步的静态方法,则会有所不同。