web-dev-qa-db-fra.com

Conseils pour éviter les blocages dans java

J'étudie Java threads et blocages, je comprends les exemples de blocage mais je me demande s'il y a des règles générales à suivre pour l'empêcher.

Ma question est de savoir s'il existe des règles ou des conseils qui peuvent être appliqués au code source dans Java pour éviter les blocages? Si oui, pourriez-vous expliquer comment l'implémenter?

44
iberck

Quelques conseils rapides dans ma tête

  • n'utilisez pas plusieurs threads (comme Swing, par exemple, en exigeant que tout se fasse dans l'EDT)
  • ne tenez pas plusieurs verrous à la fois. Si vous le faites, acquérez toujours les verrous dans le même ordre
  • ne pas exécuter de code étranger tout en maintenant un verrou
  • utiliser des serrures interruptibles
32
JB Nizet

Encapsuler, encapsuler, encapsuler! Probablement l'erreur la plus dangereuse que vous pouvez faire avec les verrous est d'exposer votre verrou au monde (le rendre public). Il est impossible de dire ce qui peut se produire si vous faites cela, car n'importe qui pourrait acquérir le verrou sans que l'objet le sache (c'est aussi pourquoi vous ne devriez pas verrouiller this). Si vous gardez votre verrou privé, vous avez un contrôle complet et cela le rend plus facile à gérer.

15
Despertar
  1. Évitez les verrous en utilisant des structures de données sans verrouillage (par exemple, utilisez un ConcurrentLinkedQueue au lieu d'un ArrayList synchronisé)
  2. Acquérir toujours les verrous dans le même ordre, par ex. attribuer une valeur numérique unique à chaque verrou et acquérir les verrous avec une valeur numérique inférieure avant d'acquérir les verrous avec une valeur numérique supérieure
  3. Libérez vos verrous après une période de temporisation (techniquement, cela n'empêche pas les blocages, cela aide simplement à les résoudre après qu'ils se soient produits)
12

Lisez et comprenez Java: concurrence et pratique. Il ne s'agit pas de "conseils" pour éviter l'impasse. Je n'embaucherais jamais un développeur qui connaissait quelques conseils pour éviter l'impasse et souvent éviter l'impasse. Il s'agit de comprendre la concurrence. Heureusement, il existe un livre complet de niveau intermédiaire sur le sujet, alors allez le lire.

10
djechlin
  1. N'utilisez pas de verrous.
  2. Si vous devez, gardez vos serrures locales. Les verrous globaux peuvent être très délicats.
  3. Faites le moins possible lorsque vous tenez le verrou.
  4. Utilisez rayures pour verrouiller uniquement les segments de vos données
  5. Préférez les types immuables. Souvent, cela signifie copier des données au lieu de partager des données.
  6. Utilisez plutôt la mécanique de comparaison et de définition (CAS), voir par exemple AtomicReference .
8
jontejj

Étant donné un choix de conception, utilisez la transmission de messages là où il n'y a que des verrous dans la file d'attente Push/pop. Ce n'est pas toujours possible mais, si c'est le cas, vous aurez très peu de blocages. Vous pouvez toujours les obtenir, mais vous devez vraiment essayer :)

5
Martin James

Il existe à peu près une seule règle importante pour éviter les blocages:

Si vous devez avoir plusieurs verrous dans votre code, assurez-vous que tout le monde les acquiert toujours dans le même ordre.

Garder votre code exempt de verrous devrait être à peu près toujours votre objectif. Vous pouvez essayer de vous en débarrasser en utilisant des objets immuables ou locaux et des structures de données sans verrouillage.

4
Keppil

Ceci est un exemple classique de blocage:

public void methodA()
{
  //...

  synchronized(lockA)
  {
     //...
     synchronized(lockB)
     {
      //...
     }
   }
}


public void methodB()
{
  //...

  synchronized(lockB)
  {
     //...
     synchronized(lockA)
     {
      //...
     }
   }
}

Ces méthodes créeraient probablement un grand blocage si elles étaient appelées par de nombreux threads. C'est parce que les objets sont verrouillés ordre différent. C'est l'une des raisons les plus courantes des blocages, donc si vous voulez les éviter, assurez-vous que les les verrous sont acquis dans l'ordre.

4
aran

Blocage dans Java est une situation de programmation où deux ou plusieurs threads sont bloqués pour toujours. Java situation de blocage se produit avec au moins deux threads et deux ou plusieurs ressources.

Comment détecter un blocage en Java

Pour détecter un blocage dans Java, nous devons regarder le vidage de thread Java de l'application, nous pouvons générer un vidage de thread en utilisant VisualVM profiler ou en utilisant l'utilitaire jstack .

Pour analyser le blocage, nous devons rechercher les threads dont l'état est [~ # ~] bloqué [~ # ~] , puis les ressources dont il s'agit en attente de verrouillage. Chaque ressource a un ID unique à l'aide duquel nous pouvons trouver quel thread détient déjà le verrou sur l'objet.

Comment éviter l'impasse en Java

Ce sont quelques-unes des directives à l'aide desquelles nous pouvons éviter la plupart des situations de blocage.

  • Évitez l'impasse en cassant la condition d'attente circulaire: Pour ce faire, vous pouvez prendre des dispositions dans le code pour imposer l'ordre sur l'acquisition et la libération des verrous. Si le verrou est acquis dans un ordre cohérent et libéré dans un ordre juste opposé, il n'y aurait pas de situation où un thread détient un verrou qui est acquis par l'autre et vice-versa.
  • Évitez les verrous imbriqués: C'est la raison la plus courante des blocages, évitez de verrouiller une autre ressource si vous en possédez déjà une. Il est presque impossible d'obtenir une situation de blocage si vous travaillez avec un seul verrou d'objet.
  • Verrouiller uniquement ce qui est requis: Vous ne devez acquérir le verrouillage que sur les ressources sur lesquelles vous devez travailler, si nous ne sommes intéressés que par l'un de ses champs, nous ne devons verrouiller que cela champ spécifique objet non complet .
  • Évitez d'attendre indéfiniment: Vous pouvez obtenir un blocage si deux threads attendent que l'autre se termine indéfiniment en utilisant la jonction de thread. Si votre thread doit attendre la fin d'un autre thread, il est toujours préférable d'utiliser join avec la durée maximale pendant laquelle vous souhaitez attendre la fin du thread .
2
amitkumar12788
  • Évitez les verrous imbriqués
  • Évitez les verrous inutiles
  • Utiliser la jointure de thread ()
1
Arun Raaj
  1. Évitez les verrous imbriqués. Il s'agit de la raison la plus courante de blocage. Évitez de verrouiller une autre ressource si vous en possédez déjà une. Il est presque impossible d'obtenir un blocage si vous travaillez avec un seul verrou d'objet.

  2. Verrouillez uniquement ce qui est requis. Comme verrouiller un champ d'objet particulier au lieu de verrouiller un objet entier si cela sert votre objectif.

  3. N'attendez pas indéfiniment.

1
027
  1. Sauf si requis, ne partagez pas les données sur plusieurs threads. Si les données ne peuvent pas être modifiées après la création/l'initialisation, respectez les variables finales.
  2. Si vous ne pouvez pas éviter les données partagées entre plusieurs threads, utilisez des blocs synchronized granulaires ou Lock s.
  3. Si vous utilisez uniquement des blocs de code synchronized, assurez-vous que les verrous sont acquis/libérés dans un certain ordre.
  4. Recherchez d'autres alternatives: volatile ou AtomicXXX variables ou Lock API

Questions SE connexes:

Évitez de synchroniser (ceci) en Java?

Différence entre volatile et synchronisé en Java

Booléen volatile vs AtomicBoolean

1
Ravindra babu