web-dev-qa-db-fra.com

Comment éviter les impasses?

Lorsque vous utilisez plusieurs threads, la mémoire partagée doit être verrouillée par des sections critiques. Cependant, l'utilisation de sections critiques entraîne des blocages potentiels. Comment peuvent-ils être évités?

29
Dimitri C.

Une façon est d'utiliser un hiérarchie des sections critiques. Si vous vous assurez qu'une section critique de parent n'est jamais entrée dans l'un de ses enfants, les blocages ne peuvent pas se produire. La difficulté consiste à appliquer cette hiérarchie.

10
Dimitri C.

La liste Related à droite de cette page contient quelques liens qui fournissent des informations intéressantes sur le sujet.

En plus de cette liste, il y a beaucoup d'autres SO questions sur le sujet, telles que 

... et beaucoup plus

5
Fredrik Mörk

Lorsque je travaille en C++, ce qui suit fonctionne pour moi:

  1. toutes les méthodes publiques (à l'exception de ctor et dtor) d'un verrou de classe threadsafe

  2. les méthodes privées ne peuvent pas appeler des méthodes publiques

Ce n'est pas une méthode générale pour éviter les impasses.

2
Rhythmic Fistman

Vous devez coder les programmes multi-threads très soigneusement. Il n'y a pas de raccourci, vous devez / comprenez le déroulement de votre programme, sinon vous serez condamné.

1
FelipeC

Vous pouvez éviter les sections critiques en utilisant message en passant au lieu de cela (appels synchrones et asynchrones). Lors de l'utilisation appels synchrones, vous devez toujours vous assurer de ne pas faire un appel circulaire, dans lequel le fil A demande au fil B une question, et B doit poser à A une question pour pouvoir répondre.

Une autre option est de faire appels asynchrones au lieu. Cependant, il est plus difficile d'obtenir des valeurs de retour.

Remarque: En effet, un système de passage de messages est mis en œuvre à l'aide d'une section critique qui verrouille la file d'attente des appels, mais celle-ci est abstraite.

1
Dimitri C.

Parmi les différentes méthodes pour entrer dans les sections critiques - les sémaphores et les mutex sont les plus populaires.

  • Un sémaphore est un mécanisme d'attente et un mutex est un mécanisme de verrouillage. Le concept est déconcertant pour la plupart des utilisateurs, mais en bref, un thread activant un mutex ne peut que le désactiver. avec ça en tête...

  • N'autorisez aucun processus à verrouiller un non partiel de ressources, si un processus nécessite 5 ressources, attendez que toutes les ressources soient disponibles. 

  • si vous utilisez sémaphore ici, vous pouvez débloquer/annuler l'attente de la ressource occupée par un autre thread. je veux dire par là que la préemption est une autre raison.

Ces 2 selon moi sont les conditions de base, les 2 autres précautions courantes peuvent être liées à celles-ci. 

Si vous n'êtes pas d'accord, ajoutez des commentaires. Je suis déjà en retard, j'ajouterai plus tard une explication plus claire et plus claire.

1
vks

Une solution consiste à utiliser une fonction de verrouillage non bloquante. Par exemple, dans Rust, vous pouvez utiliser std::sync::Mutex::try_lock au lieu de std::sync::Mutex::lock.

Donc si vous avez cet exemple de code:

fn transfer(tx: &Mutex<i32>, rx: &Mutex<i32>, amount: i32) -> () {
    let mut tx = tx.lock().unwrap();
    let mut rx = rx.lock().unwrap();

    *tx -= amount;
    *rx += amount;
}

Vous pourriez plutôt faire quelque chose comme ceci:

fn transfer(tx: &Mutex<i32>, rx: &Mutex<i32>, amount: i32) -> () {
    loop {
        // Attempt to lock both mutexes
        let mut tx = tx.try_lock();
        let mut rx = rx.try_lock();

        // If both locks were successfull,
        // i.e. if they currently are not
        // locked by an other thread
        if let Ok(ref mut tx) = tx {
            if let Ok(ref mut rx) = rx {
                // Perform the operations needed on
                // the values inside the mutexes
                **tx -= amount;
                **rx += amount;

                // Exit the loop
                break;
            }
        }
        // If at least one of the locks were
        // not successful, restart the loop
        // and try locking the values again.

        // You may also want to sleep the thread
        // here for a short period if You think that
        // the mutexes might be locked for a while.
    }
}
0
Mathias Magnusson

L'ALGORITHME SUIVANT IS UTILISÉ POUR ÉVITER LE DÉADLOCK:

Algorithme du banquier

–Imposer des conditions moins strictes que dans la prévention des blocages dans le but d'obtenir une meilleure utilisation des ressources

–État de sécurité

• Le système d’exploitation peut garantir que tous les processus en cours peuvent terminer leur travail dans un délai déterminé

–Etat non sécurisé

• N'implique pas que le système est dans une impasse, mais que le système d'exploitation ne peut garantir que tous les processus en cours pourront terminer leur travail dans un délai déterminé

–Nécessite que les ressources ne soient allouées aux processus que lorsque celles-ci donnent lieu à des états sûrs. - Il comporte un certain nombre de faiblesses (telles que le fait de requérir un nombre fixe de processus et de ressources) qui l'empêchent d'être implémenté dans des systèmes réels.

0
user2293912