Heim > Artikel > Backend-Entwicklung > Detaillierte Erläuterung der .NET-Synchronisation und des asynchronen Mutex
Dieser Aufsatz fährt fort: .NET-Synchronisierung und asynchrone Thread-sichere Sammlung (11)
Dieser Aufsatz und die nächsten beiden Aufsätze stellen den letzten großen Teil der Wissenspunkte zu .NET-Synchronisierung und asynchronem Block vor : WaitHandle-Familie.
Abstrakte Basisklasse: WaitHandle, drei Unterklassen: EventWaitHandle (Ereignisbenachrichtigung), Mutex (Prozesssynchronisationssperre), Semaphone (Semaphor) und zwei Enkel: System.Threading.AutoResetEvent, System Unterklassen von EventWaitHandle.
[ComVisibleAttribute(true)]public abstract class WaitHandle : MarshalByRefObject, IDisposable
Anhand der obigen Informationen können wir erkennen, dass WaitHandle von MarshalByRefObject erbt und die IDisposable-Schnittstelle implementiert.
Sie sind vielleicht nicht sehr vertraut mit MarshalByRefObject, aber Sie werden sicherlich viele seiner Unterklassen verwendet haben. Lassen Sie uns sein wahres Gesicht enthüllen.
MarshalByRefObject wird in MSND wie folgt beschrieben:
Die Anwendungsdomäne ist eine Partition, in der sich eine oder mehrere Anwendungen in einem Betriebssystemprozess befinden. Objekte in derselben Anwendungsdomäne kommunizieren direkt. Objekte in verschiedenen Anwendungsdomänen können auf zwei Arten kommunizieren: durch die Übertragung von Objektkopien über Anwendungsdomänengrenzen hinweg oder durch die Verwendung von Proxys zum Austausch von Nachrichten. MarshalByRefObject ist eine Basisklasse für Objekte, die über Anwendungsdomänengrenzen hinweg kommunizieren, indem sie Nachrichten mithilfe von Proxys austauschen.
Sie sind möglicherweise verwirrter, nachdem Sie das gesehen haben. Habe ich es verwendet? Seine Unterklassen verwendet? Das ist richtig, seine Unterklassen wurden verwendet und es gibt noch viele weitere.
Zum Beispiel Pinsel, Bild, Stift, Schriftart usw. im System.Drawing-Namespace, und es gibt auch einen bekannteren Stream unter dem System.IO-Namespace.
Erweiterte Lektüre: Verwenden Sie MarshalByRefObject, um AOP zu implementieren.
Da wir dies sehen, müssen wir nur wissen, dass WaitHandle die Fähigkeit hat, über Anwendungsdomänen hinweg zu kommunizieren.
Andererseits wird Monitor normalerweise nur für die Kommunikation zwischen Threads in der Anwendungsdomäne verwendet. Tatsächlich kann Monitor auch Sperren in mehreren Anwendungsdomänen bereitstellen, wenn das für die Sperre verwendete Objekt von MarshalByRefObject abgeleitet ist.
Da Mutex Betriebssystemressourcen aufrufen muss, ist sein Ausführungsaufwand viel größer als bei Monitor. Wenn Sie daher nur Vorgänge zwischen Threads innerhalb der Anwendung synchronisieren müssen, sollte Monitor/Lock die erste Wahl sein
WaitOne() /WaitOne(TimeSpan, Boolean) und mehrere Überladungen: Besitz anfordern, dieser Aufruf wird blockiert, bis der aktuelle Mutex ein Signal empfängt, oder bis Wenn das optionale Timeout-Intervall erreicht ist, muss keine dieser Methoden ein Sperrobjekt als zusätzlichen Parameter bereitstellen.
Sie können die WaitHandle.WaitOne-Methode verwenden, um den Besitz eines Mutex anzufordern. Der aufrufende Thread wird blockiert, bis eines der folgenden Ereignisse eintritt:
Der Mutex signalisiert Nichtbesitz. In diesem Fall gibt die WaitOne-Methode true zurück, übernimmt den Mutex-Besitz des aufrufenden Threads und greift auf die durch den Mutex geschützte Ressource zu. Nachdem der Thread den Zugriff auf Ressourcen abgeschlossen hat, muss die ReleaseMutex-Methode aufgerufen werden, um den Besitz des Mutex freizugeben.
hat die Methode millisecondsTimeout oder den Parameter timeout übergeben . In diesem Fall gibt die WaitOne-Methode false zurück und der Thread übernimmt zu diesem Zeitpunkt nicht den Besitz des Mutex.
ReleaseMutex(): Gibt den aktuellen Mutex einmal frei. Beachten Sie, dass dies einmal hervorgehoben wird, da der Thread, dem der Mutex gehört, die WaitOne-Funktionsreihe wiederholt aufrufen kann, ohne seine Ausführung zu blockieren, und Enter()/Exit() des Monitors wiederholt aufgerufen werden kann, nachdem die Objektsperre erworben wurde. Die Anzahl der Mutex-Aufrufe wird von der Common Language Runtime (CLR) gespeichert. Die Anzahl beträgt +1 für jeden WaitOne() und -1 für jeden ReleaseMutex() Betrachten Sie diesen Mutex. Wenn er nicht freigegeben wird, gibt es keine Möglichkeit, den Mutex zu erhalten. Darüber hinaus kann wie bei Monitor.Exit() nur der Besitzer des Mutex RleaseMutex() verwenden, andernfalls wird eine Ausnahme ausgelöst.
Wenn der Thread beendet wird, während er den Mutex besitzt, sagen wir, dass der Mutex aufgegeben wurde. Im MSDN warnt Microsoft, dass es sich hierbei um einen „schwerwiegenden“ Programmierfehler handele. Dies bedeutet, dass die Anzahl von WaitOne() und ReleaseMutex() ungleich ist, nachdem der Besitzer des Mutex den Besitz erlangt hat und der Aufrufer selbst unverantwortlich beendet wird, was dazu führt, dass sich die durch den Mutex geschützte Ressource in einem inkonsistenten Zustand befindet. Tatsächlich ist dies nichts weiter als eine Erinnerung daran, daran zu denken, Mutex in der try/finally-Struktur zu verwenden.
如果在一个应用程序域内使用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访问的安全性控制。
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; }
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der .NET-Synchronisation und des asynchronen Mutex. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!