Java thread sans danger pour vous

Q

Comment garantir la sécurité des threads en Java?

Conclusion

Tempête

Spécification du langage Java

Surtout en Java, la syntaxe de contrôle suivante est liée aux éléments qui sont apparus jusqu'à présent.

Entraine toi

Prenons le cas où foo () et bar () sont appelés à partir de différents threads plusieurs fois à des intervalles irréguliers pour l'implémentation suivante.

   public void foo() {
       _object.update();  // _Traitement pour changer l'état interne de l'objet
   }
   
   public void bar() {
       if (_object.enabled()) {
           _object.getData();  // enabled()Une exception se produit lorsqu'elle est appelée lorsque la valeur est false
       }
   }

Pas de bloc synchronisé

Puisqu'il n'y a aucune garantie d'atomicité dans le traitement de bar (), les méthodes peuvent être appelées dans l'ordre suivant. _object.enabled() -> _object.update() -> _object.getData()

   public void foo() {
       _object.update();
   }
   
   public void bar() {
       if (_object.enabled()) {
           _object.getData();  // _L'état interne de l'objet n'est pas garanti
       }
   }

Il y a un bloc synchronisé

Une garantie de synchronisation est ajoutée lors du traitement dans le bloc, c'est-à-dire que l'atomicité est également garantie. 【 _object.update() 】 -> 【 _object.enabled() -> _object.getData() 】 -> 【 _object.update() 】

Il est facile de comprendre si une image est stockée dans la file d'attente de traitement en unités de bloc.

   public void foo() {
       synchronized (this) {
           _object.update();
       }
   }
   
   public void bar() {
       synchronized (this) {
           if (_object.enabled()) {
               _object.getData();  // _L'état interne de l'objet est garanti
           }
       }
   }

Il n'y a qu'une partie du bloc synchronisé

Synchronisez les opérations entre les blocs qui spécifient le même objet comme argument

Le bloc synchronisé n'est qu'une garantie de synchronisation comme décrit ci-dessus. L'implémentation suivante ne garantit pas la synchronisation du traitement à l'intérieur de bar ().

   public void foo() {
       _object.update();
   }
   
   public void bar() {
       synchronized (this) {
           if (_object.enabled()) {
               _object.getData();  // _L'état interne de l'objet n'est pas garanti
           }
       }
   }

Bloc synchronisé pour un autre objet

Un supplément au cas où. La synchronisation n'est pas garantie pour les opérations entre des blocs qui spécifient différents objets comme arguments.

   public void foo() {
       synchronized (_SOME_OBJECT) {
           _object.update();
       }
   }
   
   public void bar() {
       synchronized (this) {
           if (_object.enabled()) {
               _object.getData();  // _L'état interne de l'objet n'est pas garanti
           }
       }
   }

De côté

À propos des objets de verrouillage

Résistance aux impasses

Afin de minimiser l'occurrence de blocage, il est souhaitable d'appliquer les principes suivants à l'implémentation.

Verrouiller la sélection d'objets

En outre, dans les deux cas, l'objet de verrouillage ne doit pas être nul. Ceci est garanti en ajoutant le modificateur final.

  //Implémentation recommandée

  class Shared {
      private final Object _LOCK_OBJECT = new Object();  //Ne le rendez pas statique

      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();
      }
  }
  //Implémentations qui l'utilisent pour les objets de verrouillage
  
  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();
          //Cette instance d'objet sert de référence à l'objet Lock de l'implémentation interne Shared.
          //Par conséquent, il viole le principe de "minimiser la plage de partage des objets de verrouillage".
      }
  }

Verrouiller la définition d'objet

De même, selon le principe de minimisation de la plage de partage, un objet de verrouillage doit être défini pour chaque cible pour laquelle la sécurité des threads doit être garantie.

  class Shared {
      //Verrouiller la cible
      private final Data _dataA = new Data();
      private final Data _dataB = new Data();
      private final Data _dateC = new Data();
      private final Validator = _validator = new Validator();

      //Verrouiller l'objet
      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();
          }
      }
  }

une chose

Recommended Posts

Java thread sans danger pour vous
Résumé des threads sûrs ~ Java ~
processus thread-safe en java
Qu'est-ce que Thread Safe (avec Java)
Les variables locales Java sont thread-safe
Traitement des threads Java
IDE 2017 pour Java
Java pour instruction
[Java] pour instruction, while instruction
[Java] Package de gestion
[Java] pour instruction / étendu pour instruction
Contre-mesures pour OutOfMemoryError en java
PNL pour Java (NLP4J) (2)
(Mémo) Java pour instruction
PNL pour Java (NLP4J) (1)
Thread de programmation Java exécutable
DateFormat n'est pas thread-safe
[Java] Nouvelle méthode de génération de threads (2)
[Java] Instruction de base pour les débutants
Livres utilisés pour apprendre Java
Test de compétence Java 2018 pour les nouveaux arrivants - Principes de base-
Java pour les débutants, masquage des données
[Java] Conseils pour l'écriture de la source
Emplacement d'installation Java pour Mac
Thread Java pour comprendre vaguement
Application Java pour les débutants: stream
Instructions Java while et for
La faible référence de JAVA a réutilisé l'instance allouée pour chaque thread
[Java] Nouvelle méthode de génération de threads (1)
Aide-mémoire C # pour les techniciens Java
Nouvelle syntaxe pour les instructions Java 12 Switch
[Java] Pouvez-vous expliquer ce phénomène?
[Pour les débutants] Résumé du constructeur java
SDK AWS pour Java 1.11.x et 2.x
Les débutants jouent à des jeux Janken en Java
Java pour les débutants, les expressions et les opérateurs 1
[Java] Mémo pour nommer les noms de classe
[Pour les débutants] Exécutez Selenium sur Java
Hello World pour le plugin Java ImageJ
[OpenCV3.2.0] Paramètres Eclipse (Java) (pour Mac)
Java pour les débutants, les expressions et les opérateurs 2
Activez OpenCV avec java8. (Pour moi-même)
Outils Spring Framework pour développeur Java
Pouvez-vous le faire? Java EE
java (utilisez le type de classe pour le champ)
Création d'un environnement de développement Java (pour Mac)
[Java & SpringBoot] Construction de l'environnement pour Mac
Remarques sur le traitement des threads Android (java)
Paramètres de débogage SSL dans Java
Génériques Kotlin pour les développeurs Java
Agenda pour la qualification Java SE 8 Silver
[Pour les débutants en Java] À propos de la gestion des exceptions
Classes et instances Java pour les débutants
Meilleures pratiques modernes pour les tests Java
Utilisez-vous Stream en Java?
[Java] Où avez-vous essayé d'utiliser java