ホームページ  >  記事  >  バックエンド開発  >  C++ マルチスレッド プログラミングにおける同時実行性の問題の分析

C++ マルチスレッド プログラミングにおける同時実行性の問題の分析

王林
王林オリジナル
2023-10-08 11:05:061241ブラウズ

C++ マルチスレッド プログラミングにおける同時実行性の問題の分析

C マルチスレッド プログラミングにおける同時実行性の問題の分析

コンピュータ ハードウェアの継続的な開発により、マルチコア プロセッサが主流になってきました。この場合、マルチコアプロセッサの性能を最大限に活用するマルチスレッド化がプログラム開発において重要な技術となっています。ただし、マルチスレッド プログラミングでは、複数のスレッド間での同時実行により、同時実行性の問題と呼ばれる問題が発生することがよくあります。この記事では、特定のコード例を使用して、C マルチスレッド プログラミングにおける同時実行の問題を分析します。

  1. スレッド間の共有リソースの競合

複数のスレッドが同時に共有リソースにアクセスして変更すると、データの競合が発生しやすくなります。データ競合の結果は予測不可能であり、プログラム エラーを引き起こす可能性があります。以下は簡単なサンプル コードです。

#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;
}

上記のコードでは、2 つのスレッドが同時にカウントを増加させます。 2 つのスレッドが同時にアクセスし、カウントを変更するため、データの競合が発生する可能性があります。上記のコードを実行した結果は未定義であり、実行するたびに異なる可能性があります。

この問題の解決策は、ミューテックス ロックまたはアトミック操作を導入することです。上記のコードを改善します。

#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;
}

改善されたコードでは、std::lock_guard<:mutex>## を通じて、ミューテックス ロック </:mutex>mtx が導入されています。 #自動ロックするにはそしてミューテックスのロックを解除します。このように、increment 関数で count が変更されると、最初にロックされ、1 つのスレッドのみが同時に共有リソースにアクセスして変更できるようになります。改良されたコードを実行すると、正しい結果が得られます。

    デッドロック
もう 1 つの一般的な同時実行の問題はデッドロックです。デッドロックとは、2 つ以上のスレッドが互いにロックを解放するのを待っている間に実行を続行できない状況です。以下は、単純なデッドロックのサンプル コードです。

#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;
}

上記のコードでは、2 つのスレッド

thread1thread2mtx1mtx1 を担当します。 ##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> lock1(mtx1);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::lock_guard<std::mutex> lock2(mtx2);

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

改良コードでは、ロックの取得順序を統一し、最初に mtx1 を取得し、次に mtx2 を取得します。これにより、デッドロックの発生が回避される。

概要:

マルチスレッド プログラミングにおける同時実行性の問題は、プログラム開発における一般的な問題の 1 つです。この記事では、同時実行の問題における共有リソースの競合とデッドロックの問題を、具体的なコード例を通じて簡単に紹介し、対応する解決策を提供します。実際のプログラミングでは、同時実行性の問題を回避し、プログラム動作の正確さと安定性を確保するために、マルチスレッド プログラミングの原理と手法をより深く理解する必要があります。

以上がC++ マルチスレッド プログラミングにおける同時実行性の問題の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。