C におけるマルチスレッド同期の問題と解決策
マルチスレッド プログラミングは、プログラムのパフォーマンスと効率を向上させる方法ですが、一連の同期の問題も引き起こします。マルチスレッド プログラミングでは、複数のスレッドが同時に共有データ リソースにアクセスして変更する可能性があり、データ競合状態、デッドロック、枯渇などの問題が発生する可能性があります。これらの問題を回避するには、同期メカニズムを使用して、スレッド間の連携と相互排他的アクセスを保証する必要があります。
C では、ミューテックス、条件変数、アトミック操作などのさまざまな同期メカニズムを使用して、スレッド間の同期の問題を解決できます。以下では、一般的な同期の問題について説明し、対応する解決策とコード例を示します。
1. 競合条件
競合条件とは、複数のスレッドが共有リソースに同時にアクセスすることを意味し、アクセス順序が不確実であるため、プログラムの実行結果が不確実になります。競合状態を回避するには、ミューテックス ロックを使用して共有リソースを保護し、1 つのスレッドのみが共有リソースにアクセスして変更できるようにする必要があります。
次は、ミューテックス ロックを使用して競合状態の問題を解決するコード例です:
#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; }
上記のコードでは、std::mutex を使用してミューテックス ロック mtx を作成します。次に、インクリメント関数で std::lock_guard<:mutex> を使用してミューテックスをロックし、1 つのスレッドのみがカウンター操作を実行できるようにします。これにより、カウンターの結果が正しく定義されることが保証されます。
2. デッドロック
デッドロックとは、2 つ以上のスレッドが互いにリソースを解放するのを待機しており、プログラムが実行を続行できなくなることを意味します。デッドロックを回避するには、RAII (リソース取得は初期化) テクノロジを使用し、マルチロック待機やその他の方法を回避できます。
次はデッドロックを回避する例です:
#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; }
上記のコードでは、std::lock_guard<:mutex std::unique_lock> を使用します。 ; これにより、ロックの取得と解放を手動で制御できます。デッドロックは、各スレッドで 1 つのミューテックスをロックし、次に別のミューテックスをロックすることで回避されます。
3. ハングリー
ハンガーとは、スレッドが何らかの理由で必要なリソースを取得できず、実行を続行できない状況を指します。飢餓を回避するために、ロック優先順位、公平なスケジューリング、およびその他のメカニズムを使用して、スレッドが公平にリソースを取得できるようにすることができます。
次は、ミューテックス ロックの優先順位を使用して飢餓問題を解決するコード例です:
#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; }
上記のコードでは、std::defer_lock パラメーターを使用して取得を遅らせます。次に、必要に応じて手動で lock.lock() を呼び出してミューテックスを取得します。これにより、スレッドがミューテックスを公平に取得し、飢餓の問題が回避されます。
概要:
マルチスレッド同期問題は、マルチスレッド プログラミングにおける重要な課題の 1 つであり、同期メカニズムの合理的な選択と使用がこれらの問題を解決する鍵となります。 C では、ミューテックス ロック、条件変数、アトミック操作を使用して、スレッド間の同期と連携を実現できます。マルチスレッド プログラムを適切に設計して作成することで、マルチスレッドの同期問題を効果的に解決し、プログラムのパフォーマンスと信頼性を向上させることができます。
以上がC++ におけるマルチスレッド同期の問題と解決策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。