2012-06-21 13 views
5

Was passiert im folgenden Code? Funktioniert die Synchronisation? Dies ist eine Interviewfrage.Was passiert, wenn die Synchronisationsvariable in Java neu zugewiesen wird?

class T 
{ 
    public static void main(String args[]) 
    { 
     Object myObject = new Object(); 
     synchronized (myObject) 
     { 
      myObject = new Object(); 
     } // end sync 
    } 
} 
+4

Ihr synchronisierter Block befindet sich in der Haupt- und nicht in einer Schleife, er wird nur einmal ausgeführt. Kein Punkt in der Synchronisierung hier (es sei denn, Sie nennen das Haupt von einem anderen Haupt, das würde komisch sein). – assylias

Antwort

4

Jedes Mal, wenn Sie den synchronisierten Block eingeben, synchronisieren Sie mit einem anderen Objekt. Meistens wird dies nichts anderes bewirken, als dich zu verwirren, aber es besteht eine geringe Chance, dass zwei Threads das gleiche Objekt sehen und warten.

Aus diesem Grund geben Ihnen Code-Analysatoren eine Warnung, wenn Sie auf einem Feld synchronisieren, das nicht final ist.

1

Es löst immer noch den gleichen Monitor, die erworben wurde, aber ein anderer Code, der auch myObject (hier unmöglich, da es eine lokale Variable ist, die Synchronisation grundsätzlich sinnlos macht) sperrt mit beginnen würde das neue Objekt zu verwenden.

Vergessen Sie nicht, dass die Synchronisation auf Objekte (oder besser, die mit Objekten verbundenen Monitore) angewendet wird - keine Variablen. Der Monitor, der erfasst/freigegeben wird, hängt nur vom Wert des Ausdrucks ab, wenn der Start des synchronisierten Blocks erreicht wird. Der Ausdruck wird nicht am Ende des synchronisierten Blocks neu ausgewertet.

0

Nein, es funktioniert nicht. Immer wenn ein neuer Thread kommt, wird ein neuer myObject erstellt. Vor allem jetzt, dass myObject eine lokale Variable ist!

Es würde nicht funktionieren, selbst wenn myObject ein Klassenmitglied ist, da Sie das Objekt ändern würden, das Sie sperren. Siehe Frage über synchronization of non-final field für längere Erklärung.

0

Ich sehe den Grund hinter diesem Code nicht, da das Objekt nicht von Threads geteilt wird. Das Entfernen des synchronisierten Blocks hat in keinem Fall Auswirkungen auf das tatsächliche Ergebnis. Es wird nur Ihren Code schneller ausführen

0

Sie müssen zunächst MyObject-Sperre erhalten, wenn diese Sperre blockiert wurde, müssen Sie warten, bis die Sperre aufgehoben wird.

Synchronisation erfordert Multithread-Umgebung. Aber Ihr Code scheint nichts mit gleichzeitig zu tun. Es tut mir leid, Ihnen zu sagen, dass nichts passieren wird.

0

Führen Sie den Code aus und analysieren Sie das Ergebnis.

public class Test { 
    static Foo o = new Foo(0); 
    static class Foo { 
     private int i = 0; 
     Foo(int i) { 
      this.i = i; 
     } 
     public void addOnce() { 
      this.i++; 
     } 
     public String toString() { 
      return String.valueOf(i); 
     } 
    } 
    public static void main(String args[]) { 
     test1(); 
     try {Thread.sleep(10000);} catch (Exception e) {} 
     test2(); 
    } 
    public static void test1() { 
     Runnable r = new Runnable() { 
      public void run() { 
       synchronized (o) { 
        System.out.println("1------>"+o); 
        o = new Foo(1); 
        try {Thread.sleep(3000);} catch (Exception e) {} 
        System.out.println("1------>"+o); 
       } 
      } 
     }; 
     new Thread(r).start(); 
     new Thread(r).start(); 
    } 
    public static void test2() { 
     Runnable r = new Runnable() { 
      public void run() { 
       synchronized (o) { 
        System.out.println("2------>"+o); 
        o.addOnce(); 
        try {Thread.sleep(3000);} catch (Exception e) {} 
        System.out.println("2------>"+o); 
       } 
      } 
     }; 
     new Thread(r).start(); 
     new Thread(r).start(); 
    } 
} 
Verwandte Themen