Lors de l'écriture d'applications multithreads, l'un des problèmes les plus courants rencontrés est les blocages.
Mes questions à la communauté sont:
Qu'est-ce qu'une impasse?
Comment les détectez-vous?
Les gérez-vous?
Et enfin, comment les empêcher de se produire?
multithreading
concurrency
locking
deadlock
bmurphy1976
la source
la source
Réponses:
Un verrou se produit lorsque plusieurs processus tentent d'accéder à la même ressource en même temps.
Un processus perd et doit attendre que l'autre se termine.
Un blocage se produit lorsque le processus en attente tient toujours une autre ressource dont le premier a besoin avant de pouvoir se terminer.
Donc, un exemple:
La ressource A et la ressource B sont utilisées par le processus X et le processus Y
Le meilleur moyen d'éviter les blocages est d'éviter que les processus ne se croisent de cette manière. Réduisez au maximum le besoin de verrouiller quoi que ce soit.
Dans les bases de données, évitez d'apporter beaucoup de modifications à différentes tables en une seule transaction, évitez les déclencheurs et passez autant que possible à des lectures optimistes / sales / nolock.
la source
Permettez-moi d'expliquer un exemple réel (pas vraiment réel) pour une situation de blocage des films policiers. Imaginez qu'un criminel tient un otage et contre cela, un flic tient également un otage qui est un ami du criminel. Dans ce cas, le criminel ne va pas laisser partir l'otage si le flic ne laisse pas son ami se laisser aller. De plus, le flic ne laissera pas l'ami du criminel se laisser aller, à moins que le criminel ne libère l'otage. Il s'agit d'une situation indigne de confiance sans fin, car les deux parties insistent sur le premier pas l'une de l'autre.
Scène criminelle et policière
Donc, simplement, lorsque deux threads ont besoin de deux ressources différentes et que chacun d'eux a le verrou de la ressource dont l'autre a besoin, c'est une impasse.
Une autre explication de haut niveau de l'impasse: Broken Hearts
Vous sortez avec une fille et un jour après une dispute, les deux côtés sont navrés l'un à l'autre et attendent un appel je-suis-désolé-et-j'ai-manqué-vous . Dans cette situation, les deux parties veulent se communiquer si et seulement si l'une d'elles reçoit un appel Je-suis-désolé de l'autre. Parce que ni l'un ni l'autre ne va commencer la communication et attendre dans un état passif, les deux vont attendre que l'autre commence la communication qui se termine dans une situation de blocage.
la source
Les blocages ne se produiront que lorsque vous avez deux ou plusieurs verrous qui peuvent être acquis en même temps et qu'ils sont saisis dans un ordre différent.
Les moyens d'éviter les blocages sont:
la source
Pour définir l'impasse, je définirais d'abord le processus.
Processus : Comme nous le savons, le processus n'est rien d'autre qu'un processus
program
en cours d'exécution.Ressource : Pour exécuter un programme, un processus nécessite des ressources. Les catégories de ressources peuvent inclure la mémoire, les imprimantes, les processeurs, les fichiers ouverts, les lecteurs de bande, les CD-ROM, etc.
Blocage : le blocage est une situation ou une condition dans laquelle deux processus ou plus détiennent des ressources et tentent d'acquérir d'autres ressources, et ils ne peuvent pas libérer les ressources tant qu'ils n'ont pas terminé leur exécution.
Condition ou situation de blocage
Dans le diagramme ci-dessus, il y a deux processus P1 et p2 et il y a deux ressources R1 et R2 .
La ressource R1 est allouée au processus P1 et la ressource R2 est allouée au processus p2 . Pour terminer l'exécution du processus, P1 a besoin de la ressource R2 , donc P1 demande pour R2 , mais R2 est déjà alloué à P2 .
De la même manière, le processus P2 pour terminer son exécution a besoin de R1 , mais R1 est déjà alloué à P1 .
les deux processus ne peuvent pas libérer leur ressource tant qu'ils n'ont pas terminé leur exécution. Les deux attendent donc une autre ressource et ils attendront éternellement. Il s'agit donc d'une condition DEADLOCK .
Pour qu'une impasse se produise, quatre conditions doivent être remplies.
et toutes ces conditions sont satisfaites dans le diagramme ci-dessus.
la source
Un blocage se produit lorsqu'un thread attend quelque chose qui ne se produit jamais.
En règle générale, cela se produit lorsqu'un thread attend un mutex ou un sémaphore qui n'a jamais été publié par le propriétaire précédent.
Cela se produit également fréquemment lorsque vous avez une situation impliquant deux threads et deux verrous comme celui-ci:
Vous les détectez généralement parce que les choses auxquelles vous vous attendez ne se produisent jamais ou que l'application se bloque complètement.
la source
Vous pouvez jeter un œil à ces merveilleux articles , dans la section Deadlock . C'est en C # mais l'idée est toujours la même pour les autres plateformes. Je cite ici pour une lecture facile
la source
Le blocage est un problème courant dans les problèmes de multitraitement / multiprogrammation sous OS. Supposons qu'il y ait deux processus P1, P2 et deux ressources R1, R2 partageables globalement et dans la section critique les deux ressources doivent être accédées
Initialement, le système d'exploitation affecte R1 pour traiter P1 et R2 pour traiter P2. Comme les deux processus s'exécutent simultanément, ils peuvent commencer à exécuter leur code, mais le PROBLÈME survient lorsqu'un processus atteint la section critique. Donc le processus R1 attendra que le processus P2 libère R2 et vice versa ... Donc ils attendront pour toujours (CONDITION DE VERROUILLAGE).
Une petite ANALOGIE ...
la source
Un blocage se produit lorsque deux threads acquièrent des verrous qui empêchent l'un ou l'autre de progresser. La meilleure façon de les éviter est de les développer soigneusement. De nombreux systèmes embarqués se protègent contre eux en utilisant une minuterie de surveillance (une minuterie qui réinitialise le système chaque fois qu'il se bloque pendant un certain temps).
la source
Un blocage se produit lorsqu'il existe une chaîne circulaire de threads ou de processus qui contiennent chacun une ressource verrouillée et essaient de verrouiller une ressource détenue par l'élément suivant de la chaîne. Par exemple, deux threads qui détiennent respectivement le verrou A et le verrou B et tentent tous deux d'acquérir l'autre verrou.
la source
Un programme classique et très simple pour comprendre la situation de blocage : -
Lorsque le thread principal appelle Lazy.main, il vérifie si la classe Lazy a été initialisée et commence à initialiser la classe. Le thread principal définit maintenant initialized sur false, crée et démarre un thread d'arrière-plan dont la méthode d'exécution définit initialized sur true et attend la fin du thread d'arrière-plan.
Cette fois, la classe est en cours d'initialisation par un autre thread. Dans ces circonstances, le thread actuel, qui est le thread d'arrière-plan, attend sur l'objet Class jusqu'à ce que l'initialisation soit terminée. Malheureusement, le thread qui effectue l'initialisation, le thread principal, attend que le thread d'arrière-plan se termine. Étant donné que les deux threads sont maintenant en attente l'un de l'autre, le programme est DEADLOCKED.
la source
Un blocage est un état d'un système dans lequel aucun processus / thread unique n'est capable d'exécuter une action. Comme mentionné par d'autres, un blocage est généralement le résultat d'une situation dans laquelle chaque processus / thread souhaite acquérir un verrou sur une ressource qui est déjà verrouillée par un autre (ou même le même) processus / thread.
Il existe différentes méthodes pour les trouver et les éviter. On réfléchit très fort et / ou on essaie beaucoup de choses. Cependant, gérer le parallélisme est notoirement difficile et la plupart des gens (sinon tous) ne pourront pas éviter complètement les problèmes.
Certaines méthodes plus formelles peuvent être utiles si vous êtes sérieux au sujet de ce type de problèmes. La méthode la plus pratique que je connaisse est d'utiliser l'approche de la théorie des processus. Ici, vous modélisez votre système dans un langage de processus (par exemple CCS, CSP, ACP, mCRL2, LOTOS) et utilisez les outils disponibles pour (modéliser) vérifier les blocages (et peut-être aussi d'autres propriétés). Les exemples d'outils à utiliser sont FDR, mCRL2, CADP et Uppaal. Certaines âmes courageuses pourraient même prouver que leurs systèmes sont sans impasse en utilisant des méthodes purement symboliques (démonstration du théorème; cherchez Owicki-Gries).
Cependant, ces méthodes formelles nécessitent généralement un certain effort (par exemple, apprendre les bases de la théorie des processus). Mais je suppose que c'est simplement une conséquence du fait que ces problèmes sont difficiles.
la source
Un blocage est une situation qui se produit lorsque le nombre de ressources disponibles est inférieur à la demande du processus différent. Cela signifie que lorsque le nombre de ressources disponibles devient inférieur à ce qu'il est demandé par l'utilisateur, à ce moment-là, le processus passe en état d'attente.Certains temps d'attente augmente davantage et il n'y a aucune chance de vérifier le problème du manque de ressources alors cette situation est connue sous le nom de blocage. En fait, le blocage est un problème majeur pour nous et il ne se produit que dans le système d'exploitation multitâche .deadlock ne peut pas se produire dans un système d'exploitation à tâche unique car toutes les ressources sont présentes uniquement pour cette tâche en cours d'exécution ......
la source
Ci-dessus quelques explications sont sympas. J'espère que cela pourra également être utile: https://ora-data.blogspot.in/2017/04/deadlock-in-oracle.html
Dans une base de données, lorsqu'une session (par exemple ora) veut une ressource détenue par une autre session (par exemple des données), mais que cette session (données) veut également une ressource qui est détenue par la première session (ora). Il peut y avoir plus de 2 sessions impliquées également mais l'idée sera la même. En fait, les blocages empêchent certaines transactions de continuer à fonctionner. Par exemple: Supposons que ORA-DATA détient le verrou A et demande le verrou B Et SKU détient le verrou B et demande le verrou A.
Merci,
la source
Un blocage se produit lorsqu'un thread attend la fin d'un autre thread et vice versa.
Comment éviter?
- Évitez les verrous imbriqués
- Évitez les verrous inutiles
- Utilisez la jointure de thread ()
Comment le détectez-vous?
exécutez cette commande dans cmd:
référence : geeksforgeeks
la source
Les blocages ne se produisent pas uniquement avec les verrous, bien que ce soit la cause la plus fréquente. En C ++, vous pouvez créer un blocage avec deux threads et aucun verrou en demandant simplement à chaque thread d'appeler join () sur l'objet std :: thread pour l'autre.
la source
Contrôle d'accès concurrentiel basé sur le verrouillage
L'utilisation du verrouillage pour contrôler l'accès aux ressources partagées est sujette à des blocages, et le planificateur de transactions seul ne peut pas empêcher leur occurrence.
Par exemple, les systèmes de bases de données relationnelles utilisent divers verrous pour garantir les propriétés ACID des transactions .
Quel que soit le système de base de données relationnelle que vous utilisez, les verrous seront toujours acquis lors de la modification (par exemple,
UPDATE
ouDELETE
) d'un certain enregistrement de table. Sans verrouiller une ligne qui a été modifiée par une transaction en cours d'exécution, Atomicity serait compromis .Qu'est-ce qu'une impasse
Comme je l'ai expliqué dans cet article , un blocage se produit lorsque deux transactions simultanées ne peuvent pas progresser car chacune attend que l'autre libère un verrou, comme illustré dans le diagramme suivant.
Étant donné que les deux transactions sont en phase d'acquisition de verrouillage, aucune des deux ne libère de verrou avant d'acquérir la suivante.
Se remettre d'une situation de blocage
Si vous utilisez un algorithme de contrôle d'accès concurrentiel qui repose sur des verrous, il existe toujours un risque de s'exécuter dans une situation de blocage. Des blocages peuvent se produire dans n'importe quel environnement de concurrence, pas seulement dans un système de base de données.
Par exemple, un programme multithreading peut se bloquer si deux ou plusieurs threads attendent des verrous qui ont été précédemment acquis afin qu'aucun thread ne puisse progresser. Si cela se produit dans une application Java, la JVM ne peut pas simplement forcer un Thread à arrêter son exécution et à libérer ses verrous.
Même si la
Thread
classe expose unestop
méthode, cette méthode est obsolète depuis Java 1.1 car elle peut laisser les objets dans un état incohérent après l'arrêt d'un thread. Au lieu de cela, Java définit uneinterrupt
méthode, qui agit comme un indice car un thread qui est interrompu peut simplement ignorer l'interruption et continuer son exécution.Pour cette raison, une application Java ne peut pas se remettre d'une situation de blocage, et il est de la responsabilité du développeur de l'application d'ordonner les demandes d'acquisition de verrou de manière à ce que les blocages ne puissent jamais se produire.
Cependant, un système de base de données ne peut pas appliquer un ordre d'acquisition de verrou donné car il est impossible de prévoir quels autres verrous une transaction donnée voudra acquérir davantage. La préservation de l'ordre de verrouillage devient la responsabilité de la couche d'accès aux données, et la base de données ne peut que faciliter la récupération après une situation de blocage.
Le moteur de base de données exécute un processus distinct qui analyse le graphique de conflit actuel pour les cycles d'attente de verrouillage (qui sont causés par des blocages). Lorsqu'un cycle est détecté, le moteur de base de données sélectionne une transaction et l'abandonne, provoquant la libération de ses verrous, afin que l'autre transaction puisse progresser.
Contrairement à la JVM, une transaction de base de données est conçue comme une unité de travail atomique. Par conséquent, une restauration laisse la base de données dans un état cohérent.
Pour plus de détails sur ce sujet, consultez également cet article .
la source
Mutex est essentiellement un verrou, fournissant un accès protégé aux ressources partagées. Sous Linux, le type de données du mutex de thread est pthread_mutex_t. Avant utilisation, initialisez-le.
Pour accéder aux ressources partagées, vous devez verrouiller le mutex. Si le mutex est déjà sur le verrou, l'appel bloquera le thread jusqu'à ce que le mutex soit déverrouillé. À la fin de la visite des ressources partagées, vous devez les déverrouiller.
Dans l'ensemble, il existe quelques principes de base non écrits:
Obtenez le verrou avant d'utiliser les ressources partagées.
Maintenir la serrure le moins longtemps possible.
Relâchez le verrou si le thread renvoie une erreur.
la source