2017-09-19 7 views
0

J'ai plusieurs threads T1, T2, T3 et T4 par exemple. T1 a la ressource A, T2 a la ressource B, T3 a la ressource A, B et C, T4 a la ressource B et C.Résolution de l'interblocage lors de l'acquisition de plusieurs verrous

Lorsque T1 arrive, il se verrouille sur A et fait un peu de travail. Puis T2 vient, il verrouille sur B et faire un peu de travail.

Suivant est T3, il se verrouille sur C mais attend sur A (pas encore B puisque A n'est pas encore acquis). Enfin pour T4 ici, il attend B (pas encore C puisque B n'est pas encore acquis).

Le pseudo-code est comme:

for all resources needed { // in case of T3, they are A and B 
    acquire lock on resource; // acquiring lock one after one 
} 

Maintenant, si T2 se termine et libère le verrou sur B, T4 est pour verrouiller éveilla sur B. Mais il faut encore attendre sur C. Alors maintenant, détient T4 B et attend sur C.

Impasse se produit lorsque T1 termine et libère le verrou sur A, T3 est éveillé pour verrouiller sur A. Mais il doit encore attendre sur B. T3 maintenant A et C et attend sur B Ensuite, j'ai T3 et T4 dans une attente infinie.

Pour résoudre ce problème, mon code pseudo changé:

while not all resource locks obtained { // in case of T3, they are A and B 
    try to lock on resource; // immediate return success or fail 
    if fail, release all unsecured locks; // in case of T3, C is secured, 
              // so only A and B may be released, 
              // in case of T4, both B and C may be released 
} 

Les travaux de code changé, mais dans mes tests, je pouvais voir T3 et T4 vérifier constamment les serrures et dans l'ensemble du programme a couru en raison plus lent à tout boucle.

Alors je fait un petit changement au code:

while not all resource locks obtained { 
    try for 1 second to lock on resource; // return after 1 second if fail 
    if fail, release all unsecured locks; 
} 

Le léger changement effectué le contrôle sur les serrures moins fréquentes et le programme couru plus vite qu'auparavant.

Je n'aime pas ce que j'ai en ce moment car il ne semble pas optimal et l'effet est plutôt aléatoire avant d'atteindre le résultat désiré. Existe-t-il une meilleure façon de résoudre la situation d'impasse mentionnée ci-dessus ou devrais-je simplement régler ce que j'ai maintenant?

Répondre

2

La prévention des interblocages est simple:

  1. Ne jamais QU'ACCROÎTRE une serrure, comme l'escalade d'un verrou de lecture dans un verrou d'écriture
  2. toujours acquérir des serrures dans le même ordre

Vous » ne fais pas la seconde. Vous essayez juste d'acquérir des verrous - bien sûr, c'est inefficace.

+0

"inefficace" est à peine le bon mot ici. – EJP

+0

@EJP Ce n'est pas * faux *, c'est juste, euh, délibérément sous-estimé. :-) –

+1

Une technique avec un débit de zéro n'est ni efficace ni inefficace: c'est faux. Si vous essayez de faire une sorte de blague, vous n'avez pas réussi. – EJP

1

La solution à tout blocage réel est de toujours acquérir les serrures dans le même ordre. Aucun dort ou réessaye requis.

+0

Oui, mais c'est essentiellement un seul thread? – user1589188

+1

@ user1589188, Certaines personnes _do_ écrivent du code dans lequel deux threads ou plus sont si étroitement couplés par des structures de données partagées et leurs verrous qu'ils ne peuvent pas fonctionner plus rapidement que (ou même rapidement) un seul programme threadé. Il appartient au concepteur du programme de rompre ce couplage serré - de trouver des moyens de laisser les threads se déclencher et de travailler indépendamment les uns des autres autant que possible. –

+0

@ user1589188 Non, ce n'est pas le cas: par exemple, tous les threads ne peuvent pas acquérir tous les verrous, mais dans tous les cas c'est le seul moyen d'éviter les interblocages, il n'y a donc rien de comparable. – EJP