2009-04-30 8 views
10

Ich habe mit einer Race Condition zu tun, glaube ich, in meiner JAVA GUI.Java anonyme Klassen und Synchronisation und "das"

Ich habe einige Methoden, die eine „anonyme Methode“ innerhalb einer anonymen Klasse wie folgt zu erstellen:

synchronized foo() 
{ 
    someMethod(new TimerTask() 
    { 
      public synchronized run() 
      { 

       //stuff 

      } 
    }; 
} 

Frage: Die run-Methode auf dem Objekt Timertask synchronisiert ist oder die Klasse, dass foo in ist?

FRAGE2: Wenn ich die "synchronisierte" in der run() -Deklaration loswerden, und stattdessen eine synchronisierte (das) {} Block innerhalb der run() - Körper hätte, würde "this" auf das TimerTask-Objekt oder verweisen zu dem Objekt, das eine Instanz der Methode ist, die foo() enthält?

Bitte helfen Sie mir hier.

Danke, JBU

+0

Dies ist ein Fehler, der sogar im JCiP-Buch (Java Concurrency In Practice) auftritt. Es ist schade, dass Java in Bezug auf die Synchronisation so schwach geschrieben ist. –

Antwort

13

Die run Methode ist auf der TimerTask selbst synchronisiert. Synchronisiert instance methods are always synchronized on this Objekt. (Klasse Methoden synchronisiert sind auf das Class Objekt.)

Wenn Sie auf dem Objekt synchronisiert werden sollen, von denen foo Mitglied ist, müssen Sie qualify the this keyword. Angenommen foo() ist ein Mitglied der Bar Klasse, in der run() Methode von TimerTask Sie können

verwenden
public void run() { 
    synchronized(Bar.this) { 
    ... 
    } 
} 
+0

"Synchronisierte Methoden werden immer für dieses Objekt synchronisiert." -Es ist schwer zu unterscheiden, welches Objekt dies in diesem Fall ist. Ist es immer nur die innerste/nächste Klasse? – jbu

+0

Ja, ich denke, man könnte es so sagen. Es ist die Instanz, von der die Methode Mitglied ist. run() ist ein Mitglied der anonymen TimerTask; foo() ist ein Member der umschließenden Instanz. – erickson

+0

Es würde mehr Spaß machen, wenn wir BGGA-Verschlüsse hätten. dies würde sich auf die innere Klasse in traditionellen (begrenzten) Schließungen beziehen, aber die äußere Klasse in BGGA (vollständiger) Schließungen. –

2

Ich bin mir ziemlich sicher, dass diese Antworten, aber ich kann eine gute Quelle atm nicht ausgraben. Die erste Frage:
synchronisiert wird die TimerTask gesperrt.

Zweite Frage:
Dies bezieht sich auf die TimerTask; Wenn Sie das enthaltende Objekt sperren möchten, verwenden Sie MyContainingObject.this

1

Es gibt nur einen Thread, der Zugriff auf Schwenkelemente haben kann. Das ist AWT-EventQueue-0. Sie müssen sich dessen bewusst sein. Wenn andere Ihrer Threads drowing oder ändern Elemente sind, gibt es sehr gute Wahrscheinlichkeit, dass Gui wird abstürzen. Um Ihre gui mit diesem Thread ausgeführt:

 
    try { 
      SwingUtilities.invokeAndWait(new Runnable(){ 
       public void run(){ 
        Swing_Prozor1 prozor = new Swing_Prozor1(); 
       } 
      }); 
     } catch (InterruptedException e) { 
      //namjerno zanemareno 
     } catch (InvocationTargetException e) { 
      //namjerno zanemareno 
     } 

und wenn Sie anonymus Klassen haben dies wird Ihnen Instanz der Klasse, in der Sie sind, also wenn Sie diese in anonymus Klasse writteing. ist eine Instanz dieser Klasse. Um Instanz der Klasse wollen Sie schreiben:

ClassName.this

hmm dies oben Code, den Sie geschrieben erzählt mir dies. Sie haben einen Teil des Codes zweimal vorgetäuscht. Wenn Sie eine synchronisierte Methode schreiben, bedeutet dies, dass nur ein Thread gleichzeitig auf diese Methode zugreifen kann. Andere Threads warten, während die synchronisierte Methode entsperrt ist.

0

Wenn Sie zum Synchronisieren der foo() und führen Sie suchen(), dann können Sie ein explizites Sperrobjekt wie

final Object lock = new Object() schaffen;

und dann darauf synchronisieren.

foo() { 
    synchronized(lock) { 
     someMethod(new TimerTask() { 
      public void run() { 
       synchronized(lock) { 
        //stuff 
       } 
      } 
     }