Frage

Was könnte das Verständnis der folgenden sein?
Ich habe in SO durch diese Post gegangen, aber immer noch mit einem Verlust es zu montieren.

code1:

synchronized(this){ 
// some code
}

code2:

Object lock = new Object();

synchronized(lock){
// some code
}

Jedes Tutorial, oder einige Links synchronisiert zu erklären, wie sie es zu einem Kind erklären?

War es hilfreich?

Lösung

Eine Sache, die nicht in den ansonsten ausgezeichneten Antworten erwähnte bereits gegeben ist, dass Unterschied zwischen code1 und code2. In code1 ist die Synchronisation auf der Instanz des Objekts in dem der Code gefunden, und in code2, dann ist es auf dem spezifische Sperrobjekt innerhalb des Objekts.

Wenn es nur die beiden synchronisierten Blöcke in der umgebenden Klasse, gibt es keine funktionelle Unterschied zwischen den beiden, aber bedenken Sie:

class CodeOneClass {
  ...
  synchronized(this) {   // or merely "synchronized" - it defaults to this
      first protected code block
  }
  ...
  synchronized(this) {   
      second protected code block
  }
...
}

class CodeTwoClass {
  ...
  Object lock1 = new Object();
  synchronized(lock1) {   
      first protected code block
  }
  ...
  Object lock2 = new Object();
  synchronized(lock2) {   
      second protected code block
  }
...
}

Wenn zwei Threads versuchen, die gleiche Instanz von CodeOneClass zu verwenden, nur einer von ihnen in sein kann, eine der beiden geschützten Codeblocks zur gleichen Zeit.

Aber mit dem zweiten Idiom, haben Sie die Flexibilität zu sagen, dass es sicher ist, für einen Thread im ersten geschützten Block zu sein, und eine andere in der anderen zu sein. Beachten Sie, dass, wenn die gleichen Sperren (beide Synchron auf dem gleichen Sperrobjekt) sind, das Verhalten als die ersten sein würde.

Es gibt noch andere Unterschiede. Einige Autoren beginnen Probleme zu hinweisen, mit synchronisiert (this) - Ich möchte Sie auf eine andere Stelle hier auf SO zeigen: Vermeiden synchronisiert (this) in Java?

Ich empfehle das Lesen es sehr, und die drei Pfosten sie verbindet.

Andere Tipps

Im Grunde gibt es eine "Sperre" in Verbindung mit jedem Objekt in Java.

Wenn ein Thread einen Aufruf synchronisiert (etwas) erreicht hat, hat er die Sperre von etwas, bevor Sie fortfahren zu erwerben. Wenn Sie nur ein Thread zu einem Zeitpunkt zulassen möchten, den Zustand eines Objekts zu ändern, die naheliegendste Sache ist, auf das Schloss des Objekts zu synchronisieren. Wenn verschiedene Methoden erlaubt sind parallel aufgerufen werden, müssen Sie verschiedene Schlösser dafür.

Wenn Sie schreiben synchronisiert (this) oder einfach synchronisiert, der Thread muss die Sperre im Zusammenhang mit dem aktuellen Objekt erwerben (von denen Methode aufgerufen wird).

Beachten Sie, dass seit Java 5.0 gibt es gleichzeitiges Paket bietet die richtige Schlösser , die anstelle der Synchronisation verwendet werden kann.

Putting-Code innerhalb eines synchronized Block im Wesentlichen bedeutet „Sobald dieser Code beginnt zu laufen, einen anderen Code, dass Bedürfnisse dieses Objekt verwenden, können nicht gleichzeitig ausgeführt werden.“

Also, wenn Thread # 2 Code in Ihrem code2 Block ausgeführt wird, wenn es um den synchronized(lock) Code kommt, hat es effektiv an allen anderen Threads schauen um zu sicherzustellen, dass niemand sonst läuft „synchronisiert“ Code mit dem lock Objekt in dem Augenblick. Fädeln # 1 sicher ausgeführt etwas Code zur gleichen Zeit, aber es könnte völlig unabhängig Code sein. Wenn ja, ist es sicher für Thread # 2 starten Sie Ihre „some code“ Sachen laufen.

Wenn dagegen Thread # 1 auf den synchronized(this) Block bekommt, hat es auch zu pausieren und sehen, ob irgendwelche anderen Threads this verwenden. Wenn this das gleiche Objekt wie lock ist, haben wir ein Problem. Uns wurde gesagt, dass nur ein Thread möglicherweise das Objekt (in einem synchronisierten Block) gleichzeitig nutzen können. Fädeln Sie noch # 2 bereits es zu benutzen. Thema # 1 müssen nur warten ... und warten ... und warten ... bis schließlich # 2 beendet Gewinde. Dann können wir fortfahren.

Das Endergebnis ist, dass nur ein synchronized Block zu einem Zeitpunkt (mit einem bestimmten Objekt, natürlich) laufen kann.

Angenommen, Sie ein Account Objekt haben, die eine Methode hat:

void debit(long debitAmount, Account beneficiary) throws InsufficientFundsException
{
   if (accountBalance >= debitAmount) {
      accountBalance -= debitAmount;
      beneficiary.credit(debitAmount);
   }
   else {
      throw new InsufficientFundsException();
   }
}

Nehmen wir nun an Sie ein Konto mit einem Guthaben von 100 Euro haben, und Sie erhalten zwei Versuche es um 70 Euro zu belasten. Wenn die beiden Belastungen bei gleichzeitig auftreten, können Sie eine Race-Bedingung erhalten wie folgt aus:

  • Erste Debit prüft Kontostand: 100> = 70, so gelingt es
  • Second Debit Schecks Kontostand: 100> = 70, so gelingt es
  • Erste abzubuchen ausführt; Kontostand wird 30
  • Second abzubuchen ausführt; Kontostand wird -40. sollte nicht erlaubt werden,

Wir können diesen schrecklichen Zustand verhindern, indem auf dem Account Objekt Sperre Synchronisierung:

void debit(long debitAmount, Account beneficiary) throws InsufficientFundsException
{
   synchronized (this) {
      if (accountBalance >= debitAmount) {
         accountBalance -= debitAmount;
         beneficiary.credit(debitAmount);
      }
      else {
         throw new InsufficientFundsException();
      }
   }
}

Dies stellt sicher, dass der Test auf den Kontostand und die Abbuchungs nicht durch einen anderen Test auf dem Kontostand unterbrochen werden.

Die Sun Java Tutorial ist ein guter Anfang Informationen über Parallelität und Verriegelung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top