1. ホーム
  2. c++

[解決済み] Mutexの例/チュートリアル?[クローズド]

2022-03-07 18:42:27

質問

私はマルチスレッドの初心者で、ミューテックスがどのように機能するかを理解しようとしていました。たくさんググってみましたが、ロックが機能しないプログラムを自作してしまったので、どのように機能するのか、まだ疑問が残っています。

ミューテックスの直感的でない構文の1つは、次のとおりです。 pthread_mutex_lock( &mutex1 ); ロックしたいのは他の変数なのに、あたかもミューテックスがロックされているように見えるのです。この構文は、ミューテックスをロックすると、そのロックが解除されるまでコードの領域がロックされるという意味でしょうか?では、スレッドはその領域がロックされたことをどのように知るのでしょうか?[ UPDATE: スレッドは、以下の方法で、領域がロックされていることを知ることができます。 メモリフェンシング ]. そして、そのような現象をクリティカルセクションというのではないのでしょうか。[ UPDATE: Critical sectionオブジェクトはWindowsでのみ利用可能で、このオブジェクトはミューテックスよりも高速で、実装しているスレッドにのみ見えるようになっています。それ以外の場合、クリティカルセクションは単にミューテックスで保護されたコードの領域を指します。 ]

要するに、最もシンプルなミューテックスでお願いします。 プログラム例 と、最もシンプルな 説明 のロジックについて教えてください。きっと役に立つと思います。 たっぷり 他の初心者の

解決方法は?

ここでは、世界中の初心者にコンセプトを説明するために、私のささやかな試みを紹介します:(a 色分け版 私のブログでも紹介しています)

多くの人が大切な人と話すために、一軒の電話ボックス(携帯電話を持っていない)に駆け込みます。最初に電話ボックスのドアの取っ手をつかんだ人が、電話を使うことを許されるのです。さもないと、他の人がハンドルを掴んで、彼を外に放り出し、彼の奥さんと話すことになります。) 行列のようなシステムはありません。その人が電話を終えてブースから出てきて、ドアの取っ手を離すと、次にドアの取っ手を掴んだ人が電話を使うことができるのです。

A スレッド は。各人
その ミュートス は: ドアの取っ手
ロック は。その人の手
は、その リソース は。電話機

同時に他のスレッドによって変更されてはならないコード行を実行しなければならないスレッド(電話を使って妻と話す)は、最初にミューテックスに対するロックを獲得しなければなりません(ブースのドアハンドルを握り締める)。そうして初めて、スレッドはそのコード行を実行できるようになる(電話をかける)。

そのコードを実行したら、スレッドはミューテックスのロックを解放して、他のスレッドがミューテックスのロックを取得できるようにしなければなりません(他の人が電話ボックスにアクセスできるようになります)。

[ 現実の排他的アクセスを考えると、ミューテックスを持つというコンセプトはちょっと無茶ですが、プログラミングの世界では、あるスレッドがすでに何行かのコードを実行していることを他のスレッドに「見せる」方法は他になかったのでしょう。再帰的ミューテックスなどの概念もありますが、この例は基本的な概念を示すだけのものです。この例でコンセプトが明確になることを願っています。 ]

C++11のスレッド機能付き。

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

std::mutex m;//you can use std::lock_guard if you want to be exception safe
int i = 0;

void makeACallFromPhoneBooth() 
{
    m.lock();//man gets a hold of the phone booth door and locks it. The other men wait outside
      //man happily talks to his wife from now....
      std::cout << i << " Hello Wife" << std::endl;
      i++;//no other thread can access variable i until m.unlock() is called
      //...until now, with no interruption from other men
    m.unlock();//man lets go of the door handle and unlocks the door
}

int main() 
{
    //This is the main crowd of people uninterested in making a phone call

    //man1 leaves the crowd to go to the phone booth
    std::thread man1(makeACallFromPhoneBooth);
    //Although man2 appears to start second, there's a good chance he might
    //reach the phone booth before man1
    std::thread man2(makeACallFromPhoneBooth);
    //And hey, man3 also joined the race to the booth
    std::thread man3(makeACallFromPhoneBooth);

    man1.join();//man1 finished his phone call and joins the crowd
    man2.join();//man2 finished his phone call and joins the crowd
    man3.join();//man3 finished his phone call and joins the crowd
    return 0;
}

を使ってコンパイルし、実行します。 g++ -std=c++0x -pthread -o thread thread.cpp;./thread

を明示的に使用する代わりに lockunlock を使用すると、ブラケットを使用することができます。 このように スコープ付きロックを使用している場合 という利点があります。 . しかし、スコープ付きロックには若干のパフォーマンス・オーバーヘッドがあります。