Antworten:
lock
ist ein Compiler-Schlüsselwort, keine tatsächliche Klasse oder ein Objekt. Es ist ein Wrapper um die Funktionalität der Monitor
Klasse und wurde entwickelt, um die Monitor
Arbeit mit dem allgemeinen Fall zu vereinfachen.
Die Monitor
(und das lock
Schlüsselwort) sind, wie Darin sagte, auf die beschränkt AppDomain
. In erster Linie, weil ein Verweis auf eine Speicheradresse (in Form eines instanziierten Objekts) erforderlich ist, um die "Sperre" zu verwalten und die Identität der zu erhaltenMonitor
Das Mutex
ist andererseits ein .Net-Wrapper um ein Betriebssystemkonstrukt und kann für die systemweite Synchronisation verwendet werden, wobei String- Daten (anstelle eines Zeigers auf Daten) als Bezeichner verwendet werden. Zwei Mutexe, die auf zwei Zeichenfolgen in zwei völlig unterschiedlichen Speicheradressen verweisen, aber dieselben Daten haben , verwenden tatsächlich denselben Mutex des Betriebssystems.
A Mutex
kann entweder prozesslokal oder systemweit sein . MSDN :
Es gibt zwei Arten von Mutexen: lokale Mutexe, die nicht benannt sind, und benannte Systemmutexe. Ein lokaler Mutex existiert nur in Ihrem Prozess.
Darüber hinaus sollte bei der Verwendung eines systemweiten Mutex auf einem System mit Terminaldiensten besondere Sorgfalt angewendet werden - auch auf derselben Seite beschrieben.
Einer der Unterschiede zwischen Mutex
und lock
besteht darin, dass Mutex
ein Konstrukt auf Kernelebene verwendet wird , sodass für die Synchronisierung immer mindestens ein Übergang zwischen Benutzerbereich und Kernelbereich erforderlich ist.
lock
- das ist wirklich eine Abkürzung zur Monitor
Klasse , versucht andererseits zu vermeiden, Kernelressourcen zuzuweisen und auf Kernelcode umzusteigen (und ist daher schlanker und schneller - wenn man ein WinAPI-Konstrukt finden muss, das ihm ähnelt, wäre es CriticalSection
).
Der andere Unterschied ist, worauf andere hinweisen: Ein Name Mutex
kann prozessübergreifend verwendet werden.
Wenn man keine besonderen Bedürfnisse hat oder eine Synchronisation zwischen Prozessen benötigt, ist es einfach besser, sich daran zu halten lock
(auch bekannt als)Monitor
) ˛ zu halten
Es gibt einige andere "geringfügige" Unterschiede, wie z. B. den Umgang mit dem Verlassen usw.
Das Gleiche gilt für ReaderWriterLock
und ReaderWriterLockSlim
in 3.5 Semaphore
und das Neue SemaphoreSlim
in .NET 4.0 usw. Es ist richtig, dass die letzteren xxSlim
Klassen nicht als systemweite Synchronisationsprimitive verwendet werden können, aber sie waren nie dazu gedacht - sie waren "nur" gemeint schneller und ressourcenschonender sein.
Ich verwende einen Mutex, um zu überprüfen, ob bereits eine Kopie der Anwendung auf demselben Computer ausgeführt wird.
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);
Es wurde bereits viel gesagt, aber um es einfach zu machen, hier ist meine Meinung.
lock -> Einfach zu verwenden, Wrapper auf dem Monitor, sperrt Threads in einer AppDomain.
unbenannter Mutex -> ähnlich wie Sperren, außer dass der Sperrbereich mehr ist und sich in einem Prozess über AppDomain erstreckt.
Benannter Mutex -> Sperrbereich ist sogar mehr als unbenannter Mutex und prozessübergreifend in einem Betriebssystem.
Jetzt sind also Optionen verfügbar. Sie müssen die auswählen, die am besten zu Ihrem Fall passt.
Mutex ist ein prozessübergreifender Prozess, und es wird ein klassisches Beispiel dafür geben, dass nicht mehr als eine Instanz einer Anwendung ausgeführt wird.
Das zweite Beispiel ist, dass Sie eine Datei haben und nicht möchten, dass unterschiedliche Prozesse auf dieselbe Datei zugreifen. Sie können einen Mutex implementieren, aber denken Sie daran, dass Mutex ein Betriebssystem ist und nicht zwischen zwei Remote-Prozessen verwendet werden kann.
Die Sperre ist der einfachste Weg, um einen Teil Ihres Codes zu schützen. Sie ist appdomänenspezifisch. Sie können die Sperre durch Monitore ersetzen, wenn Sie eine kontrollierte Synchronisation wünschen.
Einige kleinere Unterschiede, die in den Antworten nicht erwähnt wurden:
Im Fall von Sperren verwenden, können Sie sicher sein , dass die Sperre wird freigegeben , wenn eine Ausnahme innerhalb des Blockes des Schlosses geschieht.
Das ist , weil die Sperre Anwendungen Monitore unter der Haube und implementiert diese Art und Weise:
object __lockObj = x;
bool __lockWasTaken = false;
try
{
System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
// Your code...
}
finally
{
if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}
Auf jeden Fall wird die Sperre aufgehoben, und Sie müssen sie nicht manuell aufheben (wie bei den Mutexen).
Für Sperren verwenden Sie normalerweise ein privates Objekt zum Sperren (und sollten es verwenden ).
Dies geschieht aus vielen Gründen. (Weitere Informationen: siehe diese Antwort und offizielle Dokumentation ).
Im Falle von Schlössern können Sie also nicht (versehentlich) von außen auf das gesperrte Objekt zugreifen und Schäden verursachen.
Bei Mutex ist dies jedoch möglich, da es üblich ist, einen Mutex zu verwenden, der als öffentlich gekennzeichnet ist und von überall verwendet wird.