Maison > développement back-end > C++ > Analyse des problèmes de concurrence dans la programmation multithread C++

Analyse des problèmes de concurrence dans la programmation multithread C++

王林
Libérer: 2023-10-08 11:05:06
original
1292 Les gens l'ont consulté

Analyse des problèmes de concurrence dans la programmation multithread C++

Analyse des problèmes de concurrence dans la programmation multithread C++

Avec le développement continu du matériel informatique, les processeurs multicœurs sont devenus courants. Dans ce cas, l’utilisation du multithreading pour exploiter pleinement les performances des processeurs multicœurs est devenue une technologie importante dans le développement de programmes. Cependant, dans la programmation multithread, en raison d'opérations simultanées entre plusieurs threads, certains problèmes surviennent souvent. Ces problèmes sont appelés problèmes de concurrence. Cet article utilisera des exemples de code spécifiques pour analyser les problèmes de concurrence dans la programmation multithread C++.

  1. Concurrence pour les ressources partagées entre les threads

Lorsque plusieurs threads accèdent et modifient des ressources partagées en même temps, il est facile de provoquer une concurrence sur les données. Les résultats des courses aux données sont imprévisibles et peuvent provoquer des erreurs de programme. Voici un exemple de code simple :

#include <iostream>
#include <thread>

int count = 0;

void increment()
{
    for (int i = 0; i < 100000; ++i)
    {
        count++;
    }
}

int main()
{
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    std::cout << "count: " << count << std::endl;

    return 0;
}
Copier après la connexion

Dans le code ci-dessus, deux threads incrémentent simultanément le nombre. Étant donné que deux threads accèdent et modifient le nombre en même temps, une concurrence sur les données est susceptible de se produire. Le résultat de l'exécution du code ci-dessus n'est pas défini et peut être différent à chaque exécution.

La solution à ce problème est d'introduire des verrous mutex ou des opérations atomiques. Améliorez le code ci-dessus :

#include <iostream>
#include <thread>
#include <mutex>

int count = 0;
std::mutex mtx;

void increment()
{
    for (int i = 0; i < 100000; ++i)
    {
        std::lock_guard<std::mutex> lock(mtx);
        count++;
    }
}

int main()
{
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    std::cout << "count: " << count << std::endl;

    return 0;
}
Copier après la connexion

Dans le code amélioré, un verrou mutex mtx est introduit via std::lock_guard<std::mutex> Verrouille et déverrouille automatiquement les verrous mutex . De cette façon, lors de la modification de count dans la fonction increment, il sera d'abord verrouillé pour garantir qu'un seul thread puisse accéder et modifier la ressource partagée en même temps. L'exécution du code amélioré donne des résultats corrects. mtx,通过std::lock_guard<std::mutex>来对互斥锁进行自动加锁和解锁。这样,在increment函数中对count进行修改时,会先加锁,保证同一时间只有一个线程能够访问和修改共享资源。运行改进后的代码,可以得到正确的结果。

  1. 死锁

另一个常见的并发问题是死锁。死锁是指两个或多个线程相互等待对方释放锁而无法继续执行的情况。以下是一个简单的死锁示例代码:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx1, mtx2;

void thread1()
{
    std::lock_guard<std::mutex> lock1(mtx1);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::lock_guard<std::mutex> lock2(mtx2);

    std::cout << "Thread 1" << std::endl;
}

void thread2()
{
    std::lock_guard<std::mutex> lock2(mtx2);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::lock_guard<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;
}
Copier après la connexion

上述代码中,thread1thread2两个线程分别对mtx1mtx2进行加锁。但是在加锁后,它们又试图对另一个锁进行加锁,从而形成了相互等待的死锁情况。这将导致程序无法继续执行。

解决死锁问题的方法是对锁的获取顺序进行统一。即,所有线程在获取锁的时候,都按照相同的顺序获取锁。修改上述代码:

void thread1()
{
    std::lock_guard<std::mutex> lock1(mtx1);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::lock_guard<std::mutex> lock2(mtx2);

    std::cout << "Thread 1" << std::endl;
}

void thread2()
{
    std::lock_guard<std::mutex> lock1(mtx1);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::lock_guard<std::mutex> lock2(mtx2);

    std::cout << "Thread 2" << std::endl;
}
Copier après la connexion

在改进后的代码中,对锁的获取顺序进行了统一,都是先获取mtx1,再获取mtx2

    Deadlock

    Un autre problème de concurrence courant est l'impasse. Un blocage est une situation dans laquelle deux threads ou plus sont incapables de poursuivre l'exécution en attendant que l'autre libère le verrou. Ce qui suit est un exemple de code de blocage simple :

    rrreee🎜Dans le code ci-dessus, les deux threads thread1 et thread2 sont responsables de mtx1 et mtx2 effectue le verrouillage. Mais après le verrouillage, ils essaient de verrouiller un autre verrou, ce qui entraîne une situation d'impasse dans laquelle ils s'attendent mutuellement. Cela empêchera le programme de continuer. 🎜🎜La façon de résoudre le problème de blocage est d'unifier l'ordre d'acquisition du verrou. Autrement dit, tous les threads acquièrent les verrous dans le même ordre lors de l'acquisition des verrous. Modifiez le code ci-dessus : 🎜rrreee🎜Dans le code amélioré, l'ordre d'acquisition du verrou est unifié. mtx1 est acquis en premier, puis mtx2 est acquis. De cette manière, l’apparition d’un blocage est évitée. 🎜🎜Résumé : 🎜🎜Les problèmes de concurrence dans la programmation multithread sont l'un des problèmes courants dans le développement de programmes. Cet article présente brièvement les problèmes de concurrence sur les ressources partagées et de blocage dans les problèmes de concurrence à travers des exemples de code spécifiques, et fournit les solutions correspondantes. Dans la programmation réelle, nous devons avoir une compréhension plus approfondie des principes et techniques de la programmation multithread pour éviter les problèmes de concurrence et garantir l'exactitude et la stabilité du fonctionnement du programme. 🎜

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal