ミューテックスとは何ですか?


655

ミューテックスは、マルチスレッドの問題を解決するために頻繁に使用されるプログラミング概念です。コミュニティへの私の質問:

ミューテックスとは何ですか?どのように使用しますか?


2
ここでの違いに良い記事があります:barrgroup.com/Embedded-Systems/How-To/RTOS-Mutex-Semaphore
アダムデービス

mutexのチュートリアルは、問題を解決するのに役立ちます:stackoverflow.com/questions/4989451/mutex-example-tutorial
Nav

1
ミューテックスはガソリンスタンドのバスルームキーのようなもので、一度に1人だけがバスルームを使用できるようにし、現在の居住者が終了してキーが返却されるまで誰もトイレを使用できないようにします。
jonschlinkert

回答:


2154

仕事で大きな白熱した議論をしているとき、私はそのような時のために自分の机に置いてあるゴム鶏を使います。ニワトリを持っている人だけが話せる人です。ニワトリを持っていないと話せません。あなたが話したいのは、あなたが鶏肉が欲しいことを示し、それが手に入るまで待つだけです。話し終えたら、次の人に話しかけるモデレーターに鶏肉を戻すことができます。これにより、人々がお互いに話し合わないようにするだけでなく、独自の会話スペースを確保できます。

ChickenをMutexに、personをthreadに置き換えれば、基本的にはmutexの概念があります。

もちろん、ゴムのミューテックスなどはありません。ゴム鶏だけ。私の猫はかつてゴム製のネズミを飼っていましたが、彼らはそれを食べました。

もちろん、ラバーチキンを使用する前に、1つの部屋で実際に5人が必要かどうかを確認する必要があります。1人の部屋で1人ですべての作業を行うのは簡単ではありません。実際には、これは単に類推を拡張しているだけですが、あなたはアイデアを得ます。


9
すばらしい答えです。ミューテックスが実際に鶏の通過を阻止するルールであると主張することはできますか?そして、鶏はあなたがロックしているものですか?
サーヤカロット

3
@SirYakalot、つまり、ニワトリがリソースで、モデレーターがミューテックスですか?
オーウェン

157
ニワトリはミューテックスです。mu ..鶏をむさぼり食う人々は競争の糸です。モデレーターはOSです。チキンを要求すると、ロック要求が行われます。mutex.lock()を呼び出すと、スレッドはlock()で停止し、OSにロック要求を出します。ミューテックスがスレッドから解放されたことをOSが検出すると、それは単にそれをユーザーに提供し、lock()が戻ります-ミューテックスはあなたのものであり、あなたのものだけです。lock()を呼び出すとブロックされるため、他の誰もそれを盗むことはできません。mutexが自分のものである場合はブロックしてtrueを返し、mutexが使用されている場合はすぐにfalseを返すtry_lock()もあります。
ПетърПетров

4
あなたは天才です。モニターを説明するためにゴム製の鶏肉のメタファーを使用できますか?
リカルド

98
一部のプログラミング概念の起源が不明確な場合があります。初心者は、なぜ誰もが正規表現について話しているのではないかと思って回ってしまうかもしれません。正規表現が[reg] ular [ex] pressionの略語であることは明らかではありません。同様に、mutexは[mut] ual [ex] clusionの略です。これにより、用語の意味がわかりやすくなる場合があります。@TheSmurfは回答にリンクしていますが、歴史的な目的のためにここに追加するとよいでしょう。
Dodzi Dzakuma

138

Mutexは相互に排他的なフラグです。1つのスレッドを許可し、他のすべてのスレッドへのアクセスをブロックするコードセクションへのゲートキーパーとして機能します。これにより、制御されているコードが一度に1つのスレッドによってのみヒットされるようになります。完了したら、必ずミューテックスを解放してください。:)


11
ミューテックスは、コード自体のセクションとは何の関係もありません。リソースを保護します。mutexがそのコードの周囲でのみ使用される場合、そのリソースはコードセグメントである可能性がありますが、コードの複数の場所でmutexを使用し始めると、説明は失敗します。通常、コードの多くの場所からアクセスできるデータ構造を保護するためにも使用できます。
paxdiablo 2017年

73

相互排除。Wikipediaのエントリは次のとおりです。

http://en.wikipedia.org/wiki/Mutual_exclusion

mutexのポイントは、2つのスレッドを同期させることです。1つのリソースにアクセスしようとする2つのスレッドがある場合、一般的なパターンは、コードを入力する前に、最初のコードブロックがアクセスを試みてミューテックスを設定することです。2番目のコードブロックがアクセスを試みると、ミューテックスが設定されていることがわかり、コードの最初のブロックが完了するまで待機して(ミューテックスの設定を解除して)、続行します。

これがどのように達成されるかの具体的な詳細は、明らかにプログラミング言語によって大きく異なります。


65

マルチスレッドアプリケーションの場合、異なるスレッドが変数などの共通リソースを共有することがあります。多くの場合、この共有ソースには同時にアクセスできないため、一度に1つのスレッドだけがそのリソースを使用していることを確認するための構造が必要です。

この概念は「相互排除」(短いMutex)と呼ばれ、そのリソースなどを使用して、その領域内で1つのスレッドのみが許可されるようにする方法です。

それらの使用方法は言語固有ですが、多くの場合(常にではないにしても)オペレーティングシステムのミューテックスに基づいています。

関数型プログラミングなどのパラダイムにより、一部の言語ではこの構成が必要ありません(Haskell、MLが良い例です)。


26

C#では、使用される一般的なmutexはMonitorです。タイプは「System.Threading.Monitor」です。また、 ' lock(Object) 'ステートメントを介して暗黙的に使用することもできます。その使用例の1つは、シングルトンクラスを構築する場合です。

private static readonly Object instanceLock = new Object();
private static MySingleton instance;
public static MySingleton Instance
{
    lock(instanceLock)
    {
        if(instance == null)
        {
            instance = new MySingleton();
        }
        return instance;
    }
}

プライベートロックオブジェクトを使用するロックステートメントは、クリティカルセクションを作成します。前のスレッドが終了するまで待機するように各スレッドに要求します。最初のスレッドがセクションに入り、インスタンスを初期化します。2番目のスレッドは待機し、セクションに入り、初期化されたインスタンスを取得します。

静的メンバーのあらゆる種類の同期では、同様にlockステートメントを使用できます。


1
これは実装依存の答えです。また、CSでは、モニターはミューテックスとは異なります。モニターには同期メカニズムがありますが、ミューテックスは不要になるまでロックするだけです。実装の詳細またはC#のセマンティクスについてIDKが、質問のコンテキストはより広いと思います
marcoslhc

25

ミューテックスとは何ですか?

ミューテックス(実際、ミューテックスは相互排除の略です)は、スピンロックとも呼ばれ、重要な領域を保護して競合状態を防ぐために使用される最も簡単な同期ツールです。つまり、スレッドはクリティカルセクションに入る前にロックを取得する必要があります(クリティカルセクションでは、マルチスレッドは共通の変数を共有し、テーブルの更新、ファイルの書き込みなど)、クリティカルセクションを離れるとロックを解放します。

競合状態とは何ですか?

競合状態は、2つ以上のスレッドが共有データにアクセスでき、同時にそれを変更しようとすると発生します。スレッドスケジューリングアルゴリズムはいつでもスレッド間でスワップできるため、スレッドが共有データへのアクセスを試みる順序はわかりません。したがって、データの変更の結果はスレッドスケジューリングアルゴリズムに依存します。つまり、両方のスレッドがデータにアクセス/変更するために「競合」しています。

実際の例:

仕事で大きな白熱した議論をしているとき、私はそのような時のために自分の机に置いてあるゴム鶏を使います。ニワトリを持っている人だけが話せる人です。ニワトリを持っていないと話せません。あなたが話したいのは、あなたが鶏肉が欲しいことを示し、それが手に入るまで待つだけです。話し終えたら、次の人に話しかけるモデレーターに鶏肉を戻すことができます。これにより、人々がお互いに話し合わないようにするだけでなく、独自の会話スペースを確保できます。

ChickenをMutexに、personをthreadに置き換えれば、基本的にはmutexの概念があります。

@Xetius

C#での使用:

この例は、ローカルのMutexオブジェクトを使用して、保護されたリソースへのアクセスを同期する方法を示しています。ミューテックスの所有権を取得するまで、各呼び出しスレッドはブロックされるため、ReleaseMutexメソッドを呼び出してスレッドの所有権を解放する必要があります。

using System;
using System.Threading;

class Example
{
    // Create a new Mutex. The creating thread does not own the mutex.
    private static Mutex mut = new Mutex();
    private const int numIterations = 1;
    private const int numThreads = 3;

    static void Main()
    {
        // Create the threads that will use the protected resource.
        for(int i = 0; i < numThreads; i++)
        {
            Thread newThread = new Thread(new ThreadStart(ThreadProc));
            newThread.Name = String.Format("Thread{0}", i + 1);
            newThread.Start();
        }

        // The main thread exits, but the application continues to
        // run until all foreground threads have exited.
    }

    private static void ThreadProc()
    {
        for(int i = 0; i < numIterations; i++)
        {
            UseResource();
        }
    }

    // This method represents a resource that must be synchronized
    // so that only one thread at a time can enter.
    private static void UseResource()
    {
        // Wait until it is safe to enter.
        Console.WriteLine("{0} is requesting the mutex", 
                          Thread.CurrentThread.Name);
        mut.WaitOne();

        Console.WriteLine("{0} has entered the protected area", 
                          Thread.CurrentThread.Name);

        // Place code to access non-reentrant resources here.

        // Simulate some work.
        Thread.Sleep(500);

        Console.WriteLine("{0} is leaving the protected area", 
            Thread.CurrentThread.Name);

        // Release the Mutex.
        mut.ReleaseMutex();
        Console.WriteLine("{0} has released the mutex", 
            Thread.CurrentThread.Name);
    }
}
// The example displays output like the following:
//       Thread1 is requesting the mutex
//       Thread2 is requesting the mutex
//       Thread1 has entered the protected area
//       Thread3 is requesting the mutex
//       Thread1 is leaving the protected area
//       Thread1 has released the mutex
//       Thread3 has entered the protected area
//       Thread3 is leaving the protected area
//       Thread3 has released the mutex
//       Thread2 has entered the protected area
//       Thread2 is leaving the protected area
//       Thread2 has released the mutex

MSDNリファレンスMutex


1
非常に良い例
Siwei Shen申思维

22

ここにいくつかの素晴らしい答えがあります、これはミューテックスが何であるかを説明するための別の素晴らしいアナロジーです:

付きの単一トイレを検討してください。誰かが入るとき、彼らは鍵を取り、トイレは占有されます。他の誰かがトイレを使用する必要がある場合、彼らはキューで待つ必要があります。トイレ内の人物がされた場合に行う、彼らは、キュー内の次の人への鍵を渡します。分かりますよね?

ストーリーのトイレ共有リソースに、キーミューテックスに変換します。トイレの鍵をとる(鍵をかける)ことで使用できます。キーがない(ロックがロックされている)場合は、待機する必要があります。キーが人から返却されたら(ロックを解除して自由に取得できます。


ただし、c#の例では、「キーをキュー内の次の人に渡す」というキューアサーションのサポートはサポートされていません。例は、スタックまたはランダムを示しています。1、2、および3はすべて、この順序でアクセスを要求します。1つは最初に保護領域に許可され、次に3つが許可されます。キューが2番目にそれを与えたでしょう。
donvnielsen

具体的な実装や具体的なプログラミング言語については触れていません。私の例は、原則としてのmutexの高レベルの抽象化に関連しています。
陳A.

18

MUTEXを最初に理解するには、「競合状態」が何であるかを知る必要があり、それからMUTEXが必要な理由を理解するだけです。マルチスレッドプログラムがあり、2つのスレッドがあるとします。これで、ジョブキューにジョブが1つあります。最初のスレッドはジョブキューをチェックし、ジョブを見つけた後、実行を開始します。2番目のスレッドもジョブキューをチェックし、キューにジョブが1つあることを確認します。したがって、同じジョブポインターも割り当てられます。したがって、今何が起こっているのか、両方のスレッドが同じジョブを実行しています。これにより、セグメンテーション違反が発生します。これは競合状態の例です。

この問題の解決策はMUTEXです。MUTEXは、一度に1つのスレッドをロックする一種のロックです。別のスレッドがロックしたい場合、そのスレッドは単にブロックされます。

このPDFファイルのリンクのMUTEXトピックは、読む価値があります。


「MUTEXトピック」とは、セマフォのセクションを意味するものです。これは、その例がバイナリセマフォであるからですよね。
Carl G

2
Mutexは、値が1のセマフォにすぎません
marcoslhc

あなたが共有したその章の本の名前は何ですか?お願い
Omar Faroque Anik 2017

@OmarFaroqueAnik参照されている本は、New Riders Publishingによって発行されたCodeSourcery LLCによるAdvanced Linux Programmingであり、リンクされたドメインのホームページからアクセスできます。
RMart 2017年

11

ミューテックスは、複数のプロセスにわたってリソースへの排他的アクセスを強制する必要がある状況で役立ちます。スレッド間でしか機能しないため、通常のロックは役に立ちません。


それは本当ですか?個別のプロセスが独自のミューテックスコピーを作成しませんか?
レオン

0

ミューテックス:ミューテックスの略ムート UAL のEx clusion。つまり、一度に1つのプロセス/スレッドがクリティカルセクションに入ることができます。複数のスレッド/プロセスが共有リソース(変数、共有メモリなど)を更新しようとする並行プログラミングでは、予期しない結果が生じる可能性があります。(結果は、どのスレッド/プロセスが最初のアクセスを取得するかによって異なります)。

このような予期しない結果を回避するには、同期メカニズムが必要です。これにより、一度に1つのスレッド/プロセスだけがそのようなリソースにアクセスできるようになります。

pthreadライブラリは、Mutexのサポートを提供します。

typedef union
{
  struct __pthread_mutex_s
  {
    ***int __lock;***
    unsigned int __count;
    int __owner;
#ifdef __x86_64__
    unsigned int __nusers;
#endif
 int __kind;
#ifdef __x86_64__
    short __spins;
    short __elision;
    __pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV      1
# define __PTHREAD_SPINS             0, 0
#else
    unsigned int __nusers;
    __extension__ union
    {
      struct
      {
        short __espins;
        short __elision;
# define __spins __elision_data.__espins
# define __elision __elision_data.__elision
# define __PTHREAD_SPINS         { 0, 0 }
      } __elision_data;
      __pthread_slist_t __list;
    };
#endif

これは、mutexデータ型、つまりpthread_mutex_tの構造です。mutexがロックされると、__ lockは1に設定されます。ロック解除されると、__ lockは0に設定されます。

これにより、2つのプロセス/スレッドがクリティカルセクションに同時にアクセスできないようになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.