Conseils pour éviter les blocages en java
j'étudie les fils et les blocages java, je comprends les exemples de blocages mais je me demande s'il y a des règles générales à suivre pour les prévenir.
ma question Est s'il y a des règles ou des conseils qui peuvent être appliqués au code source en java pour prévenir les blocages? Si oui, pouvez-vous expliquer comment le mettre en œuvre?
11 réponses
Quelques conseils de ma tête
- n'utilisez pas plusieurs threads (comme Swing le fait, par exemple, en exigeant que tout soit fait dans L'EDT)
- ne pas tenir plusieurs serrures à la fois. Si vous le faites, toujours acquérir les serrures dans le même ordre
- n'exécute pas de code étranger en tenant une serrure
- use serrures interruptibles
Encapsuler, encapsuler, encapsuler! probablement l'erreur la plus dangereuse que vous pouvez faire avec les serrures est d'exposer votre serrure au monde (la rendre publique). Il n'y a pas de dire ce qui peut se passer si vous faites cela que n'importe qui serait en mesure d'acquérir la serrure sans que l'objet sache (c'est aussi pourquoi vous ne devriez pas verrouiller this
). Si vous gardez votre clé privée, vous avez le contrôle complet et cela le rend plus maniable.
- éviter les serrures en utilisant des structures de données sans serrure (p.ex. utiliser un
ConcurrentLinkedQueue
au lieu d'unArrayList
synchronisé) - acquérir toujours les serrures dans le même ordre, p.ex. attribuer une valeur numérique unique à chaque serrure et acquérir les serrures avec une valeur numérique inférieure avant d'acquérir les serrures avec une valeur numérique plus élevée
- Relâchez vos serrures après une période de timeout (techniquement, cela n'empêche pas les blocages, il est juste utile de resolve them after them've occurred)
Lire et comprendre Java: la Simultanéité et de la Pratique. il ne s'agit pas de" pourboires " pour éviter l'impasse. Je n'engagerais jamais un promoteur qui savait quelques conseils pour éviter l'impasse et souvent éviter l'impasse. Il s'agit de comprendre la simultanéité. Heureusement, il existe un livre complet de niveau intermédiaire sur le sujet, alors allez le lire.
- N'utilisez pas de serrures.
- si vous devez, gardez vos serrures locales. Les serrures globales peuvent être très délicates.
- faites le moins possible quand vous tenez la serrure.
- utilisez bandes pour verrouiller seulement des segments de vos données
- préfère les types immuables. Souvent, cela signifie copier des données au lieu de les partager.
- utiliser plutôt comparer et régler la mécanique (CAS) , Voir, par exemple, , référence atomique .
avec un choix de design, utilisez le message-passing où il n'y a que des serrures dans la file d'attente push/pop. Ce n'est pas toujours possible, mais, si elle l'est, vous aurez très peu de blocages. Vous pouvez encore le faire, mais vous devez l'essayer vraiment dur :)
il n'y a à peu près qu'une seule règle quand il s'agit de prévenir les impasses:
si vous avez besoin d'avoir plusieurs serrures dans votre code, assurez-vous que tout le monde les acquérir toujours dans le même ordre.
garder votre code libre des serrures devrait à peu près toujours être votre objectif. Vous pouvez essayer de vous en débarrasser en utilisant des objets immuables ou thread-local et des structures de données sans verrouillage.
C'est un exemple classique d'impasse:
public void methodA(){
synchronized(lockA){
//...
synchronized(lockB){
//...
}
}
}
public void methodB(){
synchronized(lockB){
//...
synchronized(lockA){
//...
}
}
}
cette méthode créerait probablement une grande impasse si elle était appelée par de nombreux fils. C'est parce que les objets sont verrouillés dans ordre différent . C'est l'une des raisons les plus courantes des blocages, donc si vous voulez les éviter, assurez-vous que les écluses sont acquises dans l'ordre .
-
éviter les écluses emboîtées. C'est la raison la plus fréquente de l'impasse. Évitez de verrouiller une autre ressource si vous en détenez déjà une.Il est presque impossible d'obtenir l'impasse si vous travaillez avec un seul verrou objet.
-
Verrouiller uniquement ce qui est requis. Comme verrouiller le champ particulier de l'objet au lieu de verrouiller l'objet entier s'il sert votre but.
-
N'attendez pas indéfiniment.
- sauf si nécessaire, ne partagez pas de données sur plusieurs threads. Si les données ne peuvent pas être modifiées après la création/initialisation, s'en tenir aux variables finales.
- si vous ne pouvez pas éviter le partage de données entre plusieurs threads, utilisez les blocs
synchronized
ou Lock s. - si vous n'utilisez que des blocs de code
synchronized
, assurez-vous que les serrures sont acquises/relâchées dans un certain ordre. - attention autres variantes: volatile ou AtomicXXX variables ou
Lock
API
Liées SE questions:
Éviter synchronisée(ce) en Java?
- Éviter Les Écluses Emboîtées
- Éviter Les Serrures Inutiles
- Use raccord de fil ()