ロックとミューテックスの違いは何ですか?


129

ロックとミューテックスの違いは何ですか?なぜそれらを交換して使用できないのですか?

回答:



95

lockコンパイラのキーワードであり、実際のクラスやオブジェクトではありません。これはMonitorクラスの機能のラッパーMonitorであり、一般的なケースでの作業を容易にするように設計されています。

Monitor(およびlockキーワード)ダーリンはに制限、言ったように、ありますAppDomain。主に(インスタンス化されたオブジェクトの形式の)メモリアドレスへの参照が「ロック」を管理し、Monitor

Mutex一方、オペレーティング・システム構築の周りネットラッパーであり、文字列使用、システム全体の同期のために使用することができるデータをその識別子として(代わりにデータへのポインタ)。2つの完全に異なるメモリアドレスの2つの文字列を参照するが、同じデータを持つ2つのミューテックスは、実際には同じオペレーティングシステムミューテックスを利用します。


54

Aは、Mutexであることができる、ローカルプロセスにシステム全体またはMSDN

mutexには2つのタイプがあります。名前のないローカルmutexと名前付きシステムmutexです。ローカルmutexはプロセス内にのみ存在します。

さらに、ターミナルサービスを備えたシステムでシステム全体のミューテックスを使用する場合は、同じページで詳しく説明されているように、特別な注意が必要です。

間の違いの一つMutexとは、lockつまりMutex利用カーネルレベルの構造を同期は常に、少なくともユーザ空間カーネルスペースの移行が必要となりますので、。

lock-これは実際にはMonitorクラスへのショートカットですが、一方でカーネルリソースの割り当てとカーネルコードへの移行を回避しようとします(したがって、無駄のない高速な操作です-似ているWinAPI構造を見つける必要がある場合は、そうなりますCriticalSection)。

他の違いは、他の人が指摘していることです。名前付き Mutex プロセス間で使用できます。

特別なニーズがある場合、またはプロセス間で同期が必要な場合を除き、lock(別名Monitor)に固執することをお勧めします˛

放棄の処理方法など、他にもいくつかの「小さな」違いがあります。

同じことはについて語ったことができReaderWriterLock、およびReaderWriterLockSlim3.5で、Semaphoreかつ新しいSemaphoreSlim.NET 4.0など後者のことは事実である内xxSlimのクラスは、システム全体の同期プリミティブとして使用することはできませんが、彼らはに意味されなかった-彼らは「のみ」を意味しました。より速く、よりリソースフレンドリーになります。


25

Mutexを使用して、同じマシンで実行中のアプリケーションのコピーがすでにあるかどうかを確認します。

bool firstInstance;
Mutex mutex = new Mutex(false, @"Local\DASHBOARD_MAIN_APPLICATION", out firstInstance);

if (!firstInstance)
{
    //another copy of this application running 
}
else
{
    //run main application loop here.
}
// Refer to the mutex down here so garbage collection doesn't chuck it out.
GC.KeepAlive(mutex);

8

多くのことはすでに述べられていますが、簡単にするために、ここに私の見解を示します。

ロック ->使いやすく、モニターのラッパー。AppDomain内のスレッド間でロックします。

名前のないミューテックス ->ロックに似ていますが、スコープのロックが多く、プロセス内のAppDomain全体に適用されます。

名前付きミューテックス ->ロック範囲は、名前なしミューテックスよりもさらに多く、オペレーティングシステムのプロセス全体に適用されます。

だから今オプションがあります、あなたはあなたのケースに最適なものを選択する必要があります。


ここでmstex.microsoft.com/en-us/library/…の mutexの回答と例から理解したように、名前のないmutexはロックと同じように機能します。ただし、mutex.WaitOne(1000)を使用すると、ロックがタイムアウトする可能性があります。一方、Monitor.TryEnterもその機能を提供します。前述のように、Mutexはラッパーです。したがって、名前のないミューテックスの代わりにロックまたはモニターを使用します。ただし、プロセス間でロックが必要な場合は、名前付きミューテックスが適しています。私が間違っていたら訂正してください。
コレイ

6

ミューテックスはクロスプロセスであり、アプリケーションの複数のインスタンスを実行しないという典型的な例があります。

2番目の例は、ファイルがあり、異なるプロセスが同じファイルにアクセスすることを望まない場合です。Mutexを実装できますが、Mutexはオペレーティングシステム全体で使用され、2つのリモートプロセス間で使用できないことを覚えておいてください。

ロックは、コードのセクションを保護する最も簡単な方法であり、アプリドメイン固有です。より制御された同期が必要な場合は、ロックをモニターに置き換えることができます。


1

回答で言及されていないいくつかの小さな違い:

  1. ロックを使用する場合、ロックのブロック内で例外が発生すると、ロックが確実に解放されます。
    これは、ロックが内部でモニターを使用し、次のように実装されているためです。

     object __lockObj = x;
     bool __lockWasTaken = false;
     try
     {
         System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
         // Your code...
     }
     finally
     {
         if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
     }

    したがって、いずれの場合でも、ロックは解放され、手動で解放する必要はありません(ミューテックスの場合のように)。

  2. ロックの場合、通常はプライベートオブジェクトを使用してロックします(使用する必要があります)。
    これは多くの理由で行われます。(詳細:この回答公式ドキュメントを参照してください)。

そのため、ロックの場合、ロックされたオブジェクトに外部からアクセスして(誤って)アクセスして何らかの損傷を与えることはできません
しかし、ミューテックスの場合は、パブリックとしてマークされ、どこからでも使用できるミューテックスを持つことが一般的であるため、これを行うことができます。

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