Problèmes de synchronisation multi-thread et solutions en C++
La programmation multi-thread est un moyen d'améliorer les performances et l'efficacité du programme, mais elle entraîne également une série de problèmes de synchronisation. Dans la programmation multithread, plusieurs threads peuvent accéder et modifier des ressources de données partagées en même temps, ce qui peut entraîner des conditions de course aux données, des blocages, une famine et d'autres problèmes. Pour éviter ces problèmes, nous devons utiliser des mécanismes de synchronisation pour garantir une coopération et un accès mutuellement exclusif entre les threads.
En C++, nous pouvons utiliser divers mécanismes de synchronisation pour résoudre les problèmes de synchronisation entre les threads, notamment les verrous mutex, les variables de condition et les opérations atomiques. Ci-dessous, nous discuterons des problèmes de synchronisation courants et donnerons les solutions correspondantes et des exemples de code.
1. Conditions de compétition
Une condition de compétition signifie que plusieurs threads accèdent aux ressources partagées en même temps. En raison de l'incertitude de la séquence d'accès, le résultat de l'exécution du programme est incertain. Pour éviter les conditions de concurrence, nous devons utiliser des verrous mutex pour protéger les ressources partagées et garantir qu'un seul thread peut accéder et modifier les ressources partagées.
Ce qui suit est un exemple de code d'utilisation d'un verrou mutex pour résoudre le problème de condition de concurrence critique :
#include <iostream> #include <thread> #include <mutex> std::mutex mtx; int counter = 0; void increment() { std::lock_guard<std::mutex> lock(mtx); counter++; } int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "Counter: " << counter << std::endl; return 0; }
Dans le code ci-dessus, nous utilisons std::mutex pour créer le verrou mutex mtx, puis utilisons std::lock_guard
2. Deadlock
Deadlock signifie que deux threads ou plus s'attendent pour libérer des ressources, ce qui empêche le programme de poursuivre son exécution. Afin d'éviter les blocages, nous pouvons utiliser la technologie RAII (acquisition de ressources est initialisation) et éviter l'attente multi-verrouillage et d'autres méthodes.
Ce qui suit est un exemple pour éviter les blocages :
#include <iostream> #include <thread> #include <mutex> std::mutex mtx1, mtx2; void thread1() { std::unique_lock<std::mutex> lock1(mtx1); std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 延迟10毫秒,让线程2有足够时间锁住mtx2 std::unique_lock<std::mutex> lock2(mtx2); // 访问共享资源 std::cout << "Thread 1" << std::endl; } void thread2() { std::unique_lock<std::mutex> lock2(mtx2); std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 延迟10毫秒,让线程1有足够时间锁住mtx1 std::unique_lock<std::mutex> lock1(mtx1); // 访问共享资源 std::cout << "Thread 2" << std::endl; } int main() { std::thread t1(thread1); std::thread t2(thread2); t1.join(); t2.join(); return 0; }
Dans le code ci-dessus, nous utilisons std::unique_lock
3. Hungry
La faim fait référence à une situation dans laquelle un thread ne peut pas obtenir les ressources requises pour une raison quelconque et ne peut pas continuer son exécution. Afin d'éviter la famine, nous pouvons utiliser la priorité de verrouillage, une planification équitable et d'autres mécanismes pour garantir que les threads obtiennent les ressources de manière équitable.
Ce qui suit est un exemple de code qui utilise la priorité du verrou mutex pour résoudre le problème de famine :
#include <iostream> #include <thread> #include <mutex> std::mutex mtx; int counter = 0; void increment() { std::unique_lock<std::mutex> lock(mtx, std::defer_lock); while (true) { lock.lock(); // 获取互斥锁 counter++; lock.unlock(); // 释放互斥锁 } } void decrement() { std::unique_lock<std::mutex> lock(mtx, std::defer_lock); while (true) { lock.lock(); // 获取互斥锁 counter--; lock.unlock(); // 释放互斥锁 } } int main() { std::thread t1(increment); std::thread t2(decrement); t1.join(); t2.join(); return 0; }
Dans le code ci-dessus, nous utilisons le paramètre std::defer_lock pour retarder l'acquisition du verrou mutex, puis appelons manuellement en cas de besoin lock.lock() pour obtenir le verrou mutex. Cela garantit que les threads acquièrent le mutex de manière équitable et évite les problèmes de famine.
Résumé :
Le problème de synchronisation multi-thread est l'un des défis importants de la programmation multi-thread. Une sélection et une utilisation raisonnables du mécanisme de synchronisation sont la clé pour résoudre ces problèmes. En C++, nous pouvons utiliser des verrous mutex, des variables de condition et des opérations atomiques pour réaliser la synchronisation et la coopération entre les threads. En concevant et en écrivant correctement des programmes multithreads, nous pouvons résoudre efficacement les problèmes de synchronisation multithread et améliorer les performances et la fiabilité des programmes.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!