Java-Thread sicher für Sie

Q.

Wie sollen wir die Thread-Sicherheit in Java gewährleisten?

Fazit

Sturm

Java-Sprachspezifikation

Insbesondere in Java bezieht sich die folgende Steuerungssyntax auf die bisher aufgetretenen Elemente.

Trainieren

Betrachten Sie den Fall, in dem foo () und bar () für die folgende Implementierung mehrmals in unregelmäßigen Abständen von verschiedenen Threads aufgerufen werden.

   public void foo() {
       _object.update();  // _Verarbeitung zum Ändern des internen Status des Objekts
   }
   
   public void bar() {
       if (_object.enabled()) {
           _object.getData();  // enabled()Eine Ausnahme tritt auf, wenn aufgerufen wird, wenn false ist
       }
   }

Kein synchronisierter Block

Da bei der Verarbeitung von bar () keine Garantie für die Atomizität besteht, können die Methoden in der folgenden Reihenfolge aufgerufen werden. _object.enabled() -> _object.update() -> _object.getData()

   public void foo() {
       _object.update();
   }
   
   public void bar() {
       if (_object.enabled()) {
           _object.getData();  // _Der interne Zustand des Objekts ist nicht garantiert
       }
   }

Es gibt einen synchronisierten Block

Während der Verarbeitung im Block wird eine Synchronisationsgarantie hinzugefügt, dh die Atomizität wird ebenfalls garantiert. 【 _object.update() 】 -> 【 _object.enabled() -> _object.getData() 】 -> 【 _object.update() 】

Es ist leicht zu verstehen, ob Sie ein Bild haben, das in Blockeinheiten in der Verarbeitungswarteschlange gespeichert ist.

   public void foo() {
       synchronized (this) {
           _object.update();
       }
   }
   
   public void bar() {
       synchronized (this) {
           if (_object.enabled()) {
               _object.getData();  // _Der interne Zustand des Objekts ist garantiert
           }
       }
   }

Es gibt nur einen Teil des synchronisierten Blocks

Synchronisieren Sie Operationen zwischen Blöcken, die dasselbe Objekt wie ein Argument angeben

Der synchronisierte Block ist nur eine Garantie für die Synchronisation wie oben beschrieben. Die folgende Implementierung garantiert keine Synchronisation für die Verarbeitung in bar ().

   public void foo() {
       _object.update();
   }
   
   public void bar() {
       synchronized (this) {
           if (_object.enabled()) {
               _object.getData();  // _Der interne Zustand des Objekts ist nicht garantiert
           }
       }
   }

Synchronisierter Block für ein anderes Objekt

Eine Ergänzung für alle Fälle. Die Synchronisierung ist für Vorgänge zwischen Blöcken, die unterschiedliche Objekte als Argumente angeben, nicht garantiert.

   public void foo() {
       synchronized (_SOME_OBJECT) {
           _object.update();
       }
   }
   
   public void bar() {
       synchronized (this) {
           if (_object.enabled()) {
               _object.getData();  // _Der interne Zustand des Objekts ist nicht garantiert
           }
       }
   }

Beiseite

Informationen zu Sperrobjekten

Dead Lock-Widerstand

Um das Auftreten eines Deadlocks zu minimieren, ist es wünschenswert, die folgenden Prinzipien auf die Implementierung anzuwenden.

Objektauswahl sperren

In beiden Fällen darf das Sperrobjekt auch nicht null sein. Dies wird durch Hinzufügen des letzten Modifikators garantiert.

  //Empfohlene Implementierung

  class Shared {
      private final Object _LOCK_OBJECT = new Object();  //Mach es nicht statisch

      public void foo() {
          synchronized (_LOCK_OBJECT) {
              // do something
          }
      }

      public void bar() {
          synchronized (_LOCK_OBJECT) {
              // do something
          }
      }
  }

  class User {
      public void sample() {
          final Shared object = new Shared();
          new Thread(() -> object.foo()).start();
          new Thread(() -> object.bar()).start();
      }
  }
  //Implementierungen, die dies für Sperrobjekte verwenden
  
  class Shared {
      public void foo() {
          synchronized (this) {
              // do something
          }
      }
      public void bar() {
          synchronized (this) {
              // do something
          }
      }
  }

  class User {
      public void sample() {
          final Shared object = new Shared();
          //Diese Objektinstanz dient als Referenz auf das Sperrobjekt der gemeinsam genutzten internen Implementierung
          //Daher verstößt es gegen das Prinzip "Minimierung des Freigabebereichs von Sperrobjekten".
      }
  }

Objektdefinition sperren

In ähnlicher Weise sollte gemäß dem Prinzip der Minimierung des Freigabebereichs für jedes Ziel, für das die Thread-Sicherheit gewährleistet werden soll, ein Sperrobjekt definiert werden.

  class Shared {
      //Ziel anvisieren
      private final Data _dataA = new Data();
      private final Data _dataB = new Data();
      private final Data _dateC = new Data();
      private final Validator = _validator = new Validator();

      //Objekt sperren
      private final Object _DATA_A_LOCK = new Object();
      private final Object _DATA_B_LOCK = new Object();
      private final Object _DATA_C_LOCK = new Object();

      public void foo() {
          synchronized (_DATA_A_LOCK) {
              _dataA.update();
          }
          synchronized (_DATA_B_LOCK) {
              _dataB.update();
          }
          synchronized (_DATA_C_LOCK) {
              _validator.execute();
              _dataC.update();
          }
      }

      public void bar() {
          synchronized (_DATA_A_LOCK) {
              _dataA.get();
          }
          synchronized (_DATA_B_LOCK) {
              _dataB.get();
          }
          synchronized (_DATA_C_LOCK) {
              _validator.execute();
              _dataC.get();
          }
      }
  }

eine Sache

Recommended Posts

Java-Thread sicher für Sie
Thread sichere Zusammenfassung ~ Java ~
Thread-sicherer Prozess in Java-Sprache
Was ist Thread-sicher (mit Java)
Lokale Java-Variablen sind threadsicher
Java-Thread-Verarbeitung
2017 IDE für Java
Java für Anweisung
[Java] für Anweisung, während Anweisung
[Java] Paket für die Verwaltung
[Java] für Anweisung / erweitert für Anweisung
Gegenmaßnahmen für OutOfMemoryError in Java
NLP für Java (NLP4J) (2)
(Memo) Java für Anweisung
NLP für Java (NLP4J) (1)
Java Programming Thread Runnable
DateFormat ist nicht threadsicher
[Java] Neue Thread-Generierungsmethode (2)
[Java] Grundlegende Aussage für Anfänger
Bücher zum Erlernen von Java
2018 Java Proficiency Test für Newcomer-Basics-
Java für Anfänger, Daten verstecken
[Java] Tipps zum Schreiben der Quelle
Java-Installationsort für Mac
Java-Thread locker zu verstehen
Java-Anwendung für Anfänger: Stream
Java während und für Anweisungen
Die schwache Referenz von JAVA hat die für jeden Thread zugewiesene Instanz wiederverwendet
[Java] Neue Thread-Generierungsmethode (1)
C # Spickzettel für Java-Techniker
Neue Syntax für Java 12 Switch-Anweisungen
[Java] Können Sie dieses Phänomen erklären?
[Für Anfänger] Zusammenfassung des Java-Konstruktors
AWS SDK für Java 1.11.x und 2.x.
Anfänger spielen Janken-Spiele in Java
Java für Anfänger, Ausdrücke und Operatoren 1
[Java] Memo zum Benennen von Klassennamen
[Für Anfänger] Führen Sie Selenium auf Java aus
Hallo Welt für ImageJ Java Plugin
[OpenCV3.2.0] Eclipse (Java) -Einstellungen (für Mac)
Java für Anfänger, Ausdrücke und Operatoren 2
Aktivieren Sie OpenCV mit Java8. (Für mich)
Spring Framework-Tools für Java-Entwickler
Kannst du es machen? Java EE
Java (Klassentyp für Feld verwenden)
Erstellen einer Java-Entwicklungsumgebung (für Mac)
[Java & SpringBoot] Umgebungskonstruktion für Mac
Einstellungen für das SSL-Debugging in Java
Kotlin-Generika für Java-Entwickler
Tagebuch für Java SE 8 Silber Qualifikation
[Für Java-Anfänger] Informationen zur Ausnahmebehandlung
Klassen und Instanzen Java für Anfänger
Moderne Best Practices für Java-Tests
Verwenden Sie Stream in Java?
[Java] Wo haben Sie versucht, Java zu verwenden?