2017-09-11 1 views
2

Ich möchte Objekte zwischen Threads synchronisieren, diese Objekte eine abstrakte Klasse erweitern:Wie funktionieren synchronisierte Methoden in der abstrakten Klasse?

public abstract class GraphicObject { 

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

class Circle extends GraphicObject { 

} 
class Rectangle extends GraphicObject { 

} 

diese Testklasse vor:

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(); 
     } 
    } 
} 

In diesem Fall a und b sind indipendent Objekte mit der gleichen abstrakten Klasse. Sind test() Methode zusammen synchronisiert oder nicht? Wenn ein Thread-Aufruf a.test() ist b.test() für alle anderen Threads gesperrt?

Ich erwarte nein, weil sie verschiedene Objekte sind.

+0

Haben Sie versucht, es zu kompilieren? –

+0

ja, aber ich habe meinen Code vereinfacht, also habe ich etwas entfernt. Jetzt bearbeite ich die Testklasse, um kompilierbar zu sein, aber meine Frage war wirklich theoretisch – Tobia

+0

Ich bin nicht wirklich sicher, dass die verknüpfte Frage die gleiche ist. – Tobia

Antwort

1

Zuerst wird Ihr Code nicht kompilieren; Sie können keine abstrakte Methode mit body verwenden, und eine abstrakte Methode kann nicht als synchronisiert markiert werden, obwohl die letzte eine design choice war.

Im Allgemeinen synchronized Schlüsselwort auf eine Methode funktioniert genauso:

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

was bedeutet, dass sie auf einer Instanz eines Objekts synchronisiert ist, was wiederum bedeutet, dass diese zwei Methoden in Ihrem Beispiel auf eine synchronisierte andere Sperre, auf a oder b jeweils.

+0

Dies ist nicht wahr, https://stackoverflow.com/questions/12805698/why- cant-an-abstract-methode-be-synchronized –

+0

ok, ich habe das 'abstract' auf seiner Methode mit body nicht bemerkt. Es wird nicht kompiliert. – Dariusz

+0

Ich bearbeite den Code removeind die doppelte abstrakte keywork, das war ein Typ. Jetzt sollte es kompilieren. – Tobia

2

Ihre test() Methode wird für die Instanz synchronisiert. So, wie a und b sind verschiedene Instanzen (auch aus verschiedenen Klassen), werden sie nicht gegeneinander gesperrt werden.

Wenn Sie dieses Verhalten mögen, müssen Sie so etwas wie

synchronized (GraphicObject.class) { 
    ... 
} 

verwenden und das kann nur in Verfahren Implementierungen durchgeführt werden, so dass keine Chance, es von der abstrakten übergeordneten Klasse zu erzwingen.

1

Jede Synchronisation ist an die Instanz gebunden, an der die Methode aufgerufen wird. Es spielt keine Rolle, ob es eine abstrakte Methode ist oder nicht; In Ihrem Beispiel wäre die einzige Möglichkeit, eine Sperre in Ihrem Beispiel zu erzeugen, der Aufruf von a.test() aus zwei verschiedenen Threads, da die Synchronisation über a, nicht test() ist. Dies wäre anders, wenn es sich um eine statische Methode handeln würde, die über die Klasse synchronisiert wird.

4

Eine abstrakte Methode kann nicht synchronisiert werden. Dies ist in JLS 8.4.3:

Es ist ein Fehler bei der Kompilierung, wenn eine Methode Erklärung, die das Schlüsselwort Zusammenfassung enthält auch eine der Schlüsselwort enthält privater, statisch, final, gebürtig, strictfp oder synchronisiert.

Die konkrete Methode, die die abstrakte Deklaration überschreibt, kann synchronisiert werden; In diesem Fall funktioniert es wie jede andere synchronisierte Methode: Es sperrt die this Instanz.

+0

Ich habe keinen Kompilierfehler gefunden, meine IDE (Eclipse) kompiliert sie. – Tobia

+0

Mit Ihrer Eingabe ist 'test()' keine abstrakte Methode mehr. Sie haben nach der abstrakten Synchronisierungsmethode gefragt, aber dann Ihre Frage so bearbeitet, dass sie keine enthält. – yshavit

+0

Ok, aber jetzt test() ist synchronisiert? – Tobia

Verwandte Themen