Risposte:
lock
è una parola chiave del compilatore, non una classe o un oggetto reali. È un involucro attorno alla funzionalità della Monitor
classe ed è progettato per rendere Monitor
più facile lavorare con il caso comune.
Il Monitor
(e la lock
parola chiave) sono, come diceva Darin, limitati al AppDomain
. Principalmente perché è necessario un riferimento a un indirizzo di memoria (nella forma di un oggetto istanziato) per gestire il "blocco" e mantenere l'identità delMonitor
La Mutex
, d'altra parte, è un Net involucro attorno ad un costrutto sistema operativo, e può essere utilizzato per la sincronizzazione a livello di sistema, utilizzando stringa dati (anziché un puntatore ai dati) come identificatore. Due mutex che fanno riferimento a due stringhe in due indirizzi di memoria completamente diversi, ma con gli stessi dati , utilizzeranno effettivamente lo stesso mutex del sistema operativo.
A Mutex
può essere locale in un processo o in tutto il sistema . MSDN :
I mutex sono di due tipi: mutex locali, che sono senza nome, e denominati mutex di sistema. Un mutex locale esiste solo all'interno del processo.
Inoltre, si dovrebbe prestare particolare attenzione - anche nella stessa pagina - quando si utilizza un mutex a livello di sistema su un sistema con Servizi terminal.
Una delle differenze tra Mutex
e lock
è che Mutex
utilizza un costrutto a livello di kernel , quindi la sincronizzazione richiederà sempre almeno una transizione spaziale spazio-kernel dell'utente.
lock
- questo è davvero un collegamento alla Monitor
classe , d'altra parte cerca di evitare l'allocazione delle risorse del kernel e la transizione al codice del kernel (ed è quindi più snella e più veloce - se si deve trovare un costrutto WinAPI che assomigli, sarebbe CriticalSection
).
L'altra differenza è ciò che gli altri sottolineano: un nome Mutex
può essere utilizzato in tutti i processi.
A meno che uno non abbia esigenze particolari o richieda la sincronizzazione tra i processi, è meglio attenersi a lock
(aka Monitor
) ˛
Esistono molte altre differenze "minori", come la gestione dell'abbandono, ecc.
Lo stesso si può dire di ReaderWriterLock
e ReaderWriterLockSlim
in 3.5, Semaphore
e il nuovo SemaphoreSlim
in .NET 4.0 ecc. È vero che queste ultime xxSlim
classi non possono essere usate come primitive di sincronizzazione a livello di sistema, ma non sono mai state pensate per - erano "solo" intese per essere più veloce e più attento alle risorse.
Uso un Mutex per verificare se ho già una copia dell'applicazione in esecuzione sullo stesso computer.
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);
Molto è già stato detto, ma per semplificare, ecco la mia opinione.
lock -> Semplice da usare, wrapper sul monitor, blocca i thread in un AppDomain.
senza nome mutex -> simile a lock tranne che l'ambito di blocco è più ed è attraverso AppDomain in un processo.
Nominato mutex -> l'ambito di blocco è persino più di un mutex senza nome ed è un processo trasversale in un sistema operativo.
Quindi ora ci sono opzioni, devi scegliere quella più adatta al tuo caso.
Mutex è un processo incrociato e ci sarà un classico esempio di non eseguire più di un'istanza di un'applicazione.
Il secondo esempio è che stai avendo un file e non vuoi che processi diversi accedano allo stesso file, puoi implementare un Mutex ma ricorda una cosa che Mutex è un sistema operativo a livello e non può essere usato tra due processi remoti.
Il blocco è un modo più semplice per proteggere la sezione del codice ed è specifico per dominio, è possibile sostituire il blocco con i monitor se si desidera una sincronizzazione più controllata.
Poche altre differenze minori che non sono state menzionate nelle risposte:
Nel caso di utilizzo di blocchi, si può essere certi che il blocco verrà rilasciato quando si verifica un'eccezione all'interno del blocco del blocco.
Questo perché il blocco utilizza monitor sotto il cofano ed è implementato in questo modo:
object __lockObj = x;
bool __lockWasTaken = false;
try
{
System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
// Your code...
}
finally
{
if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}
Pertanto, in ogni caso, il blocco viene rilasciato e non è necessario rilasciarlo manualmente (come si farebbe per i mutex).
Per i Lock, di solito usi un oggetto privato per bloccare (e dovresti usare ).
Questo è fatto per molte ragioni. (Altre informazioni: vedi questa risposta e documentazione ufficiale ).
Pertanto, in caso di blocchi, non è possibile (ottenere accidentalmente) l'accesso all'oggetto bloccato dall'esterno e causare alcuni danni.
Ma nel caso di Mutex, puoi, poiché è comune avere un Mutex che è contrassegnato come pubblico e utilizzato da qualsiasi luogo.