ホームページ  >  記事  >  バックエンド開発  >  .NETの同期と非同期ミューテックスの詳細説明

.NETの同期と非同期ミューテックスの詳細説明

迷茫
迷茫オリジナル
2017-03-26 16:10:262515ブラウズ

このエッセイの続き: .NET の同期と非同期のスレッドセーフ コレクション (11)

このエッセイと次の 2 つのエッセイでは、.NET の同期と非同期シリーズの最後の大きな知識ポイントである WaitHandle ファミリを紹介します。

抽象基本クラス: WaitHandle、3 つのサブクラス: EventWaitHandle (イベント通知)、Mutex (プロセス同期ロック)、Semaphone (セマフォ)、および 2 つの孫クラス: System.Threading.AutoResetEvent、System.Threading.ManualResetEvent、すべて EventWaitHandle のサブクラスです。 。

1. 抽象基本クラス WaitHandle

[ComVisibleAttribute(true)]public abstract class WaitHandle : MarshalByRefObject, IDisposable

上記の情報から、WaitHandle が MarshalByRefObject を継承し、IDisposable インターフェイスを実装していることがわかります。

MarshalByRefObject についてはあまり馴染みがないかもしれませんが、そのサブクラスの多くを使用したことがあるはずです。その正体を明らかにしましょう。

MarshalByRefObject は、MSND では次のように説明されています。

アプリケーション ドメインは、オペレーティング システム プロセス内に 1 つ以上のアプリケーションが存在するパーティションです。同じアプリケーション ドメイン内のオブジェクトは直接通信します。異なるアプリケーション ドメイン内のオブジェクトは、アプリケーション ドメインの境界を越えてオブジェクトのコピーを転送する方法と、プロキシを使用してメッセージを交換する方法の 2 つの方法で通信できます。 MarshalByRefObject は、プロキシを使用してメッセージを交換することでアプリケーション ドメインの境界を越えて通信するオブジェクトの基本クラスです。

これを見た後はさらに混乱するかもしれません。 そのサブクラスを使用しましたか? そうです、そのサブクラスが使用されており、さらに多くのサブクラスがあります。

たとえば、System.Drawing 名前空間にはブラシ、画像、ペン、フォントなどがあり、System.IO 名前空間には、よりよく知られた Stream もあります。

詳細な読み方: AOP を実装するには、MarshalByRefObject を使用します。

これを見ると、WaitHandle にはアプリケーション ドメイン間で通信する機能があることだけを知る必要があります。

2. Mutex (プロセス同期ロック)

1. MSDN では、Mutex をプロセス間の同期プリミティブ、つまりロックの概念として定義しています。

一方、Monitorは通常、アプリケーションドメイン内のスレッド間の通信にのみ使用されます。実際、ロックに使用されるオブジェクトが MarshalByRefObject から派生している場合、Monitor は複数のアプリケーション ドメインでロックを提供することもできます。

Mutexはオペレーティングシステムのリソースを呼び出す必要があるため、実行のオーバーヘッドがMonitorよりもはるかに大きいため、アプリケーション内のスレッド間の操作のみを同期する必要がある場合は、Monitor/lockを最初の選択肢にする必要があります

2。

  • WaitOne() /WaitOne(TimeSpan, Boolean) およびいくつかのオーバーロード: 所有権を要求します。この呼び出しは、現在のミューテックスがシグナルを受信するまで、またはオプションのタイムアウト間隔に達するまでブロックされます。これらのメソッドはロックを提供する必要はありません。オブジェクトを追加パラメータとして使用します。

    • WaitHandle.WaitOne メソッドを使用して、ミューテックスの所有権を要求できます。 次のいずれかが発生するまで、呼び出しスレッドはブロックされます:

    • ミューテックス信号が所有されていない。 この場合、WaitOne メソッドは true を返し、呼び出しスレッドからミューテックスの所有権を取得し、ミューテックスによって保護されているリソースにアクセスします。 スレッドがリソースへのアクセスを完了した後、ReleaseMutex メソッドを呼び出して、ミューテックスの所有権を解放する必要があります。

    • には、経過した WaitOne への呼び出しで指定されたメソッド millisecondsTimeout または timeout パラメーターがあります。 この場合、WaitOne メソッドは false を返し、現時点ではスレッドはミューテックスの所有権を取得しません。

  • ReleaseMutex(): 現在の Mutex を 1 回解放します。ミューテックスを所有するスレッドは、その実行をブロックすることなく WaitOne 一連の関数を繰り返し呼び出すことができるため、この点は一度強調しておきます。これと、Monitor の Enter()/Exit() は、オブジェクト ロックを取得した後に繰り返し呼び出すことができます。 Mutex が呼び出された回数は、共通言語ランタイム (CLR) によって保存されます。このカウントは、WaitOne() ごとに +1、ReleaseMutex() ごとに -1 になります。このカウントが 0 でない限り、他の Mutex ウェイターは保存されます。このミューテックスを検討してください。ミューテックスが解放されていない場合、ミューテックスを取得する方法はありません。 さらに、Monitor.Exit() と同様に、Mutex の所有者のみが RleaseMutex() を実行できます。それ以外の場合は、例外がスローされます。

  • ミューテックスを所有している間にスレッドが終了した場合、そのミューテックスは放棄されたと呼ばれます。 Microsoft は MSDN で、これは「重大な」プログラミング エラーであると警告しています。これは、ミューテックスの所有者が所有権を取得した後、WaitOne() と ReleaseMutex() の数が等しくなくなり、呼び出し元自体が無責任に終了し、ミューテックスによって保護されているリソースが不整合な状態になることを意味します。実際、これは try/finally 構造で Mutex を使用することを忘れないように注意するためのものにすぎません。

3、全局和局部的Mutex

如果在一个应用程序域内使用Mutex,当然不如直接使用Monitor/lock更为合适,因为前面已经提到Mutex需要更大的开销而执行较慢。不过Mutex毕竟不是Monitor/lock,它生来应用的场景就应该是用于进程间同步的。用于在进程间通讯的Mutex我们称为全局Mutex,而只用于在应用程序域内部通讯的Mutex、我们称为局部Mutex.

全局Mutex和局部Mutex是通过构造函数来构造不同的实例的,让我们来看一下Mutex的构造函数,一共有5个,挑两个具有代表性的看一下吧:

  • Mutex():用无参数的构造函数得到的Mutex没有任何名称,而进程间无法通过变量的形式共享数据,所以没有名称的Mutex也叫做局部(Local)Mutex。另外,这样创建出的Mutex,创建者对这个实例并没有拥有权,仍然需要调用WaitOne()去请求所有权。

  • Mutex(Boolean initiallyOwned, String name, out Booldan createdNew, MutexSecurity):第一个bool参数:指示初始化的实例是否拥有互斥体所有权。第二个string类型、为互斥体指定一个名称,如果string为null或者空字符串 则相当于创建一个没有名字的Mutex,当属于局部Mutex. 而有名字的Mutex当属于全局Mutex.第三个bool参数、如果已经初始化了互斥体 返回True, 如果互斥体已经存在则返回False. 最后一个参数用于Mutex访问的安全性控制。

4、用途 

Mutex天生为进程间的同步基元,因此它可以用来控制应用程序的单实例

/// <summary>/// 单实例运行/// </summary>/// <returns> true 应用程序已启动,false 则没有 
</returns>public bool SingleRun(ref System.Threading.Mutex mutex )
{
    mutex = new System.Threading.Mutex(false, "WINDOWS");    
    if (!mutex.WaitOne(0, false))
    {
        mutex.Close();
        mutex = null;
    }    if (mutex == null)
    {        return true;
    }    return false;
}

以上が.NETの同期と非同期ミューテックスの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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