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?
Quelques conseils rapides dans ma tête
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.
ConcurrentLinkedQueue
au lieu d'un ArrayList
synchronisé)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.
É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 :)
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.
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.
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.
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.
Ce sont quelques-unes des directives à l'aide desquelles nous pouvons éviter la plupart des situations de blocage.
É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.
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.
N'attendez pas indéfiniment.
synchronized
granulaires ou Lock s.synchronized
, assurez-vous que les verrous sont acquis/libérés dans un certain ordre.Lock
APIQuestions SE connexes:
Évitez de synchroniser (ceci) en Java?