Quand est-il approprié d'utiliser la Monitor
classe ou le lock
mot - clé pour la sécurité des threads en C #?
EDIT:
Il semble, d'après les réponses jusqu'à présent, que ce lock
soit un raccourci pour une série d'appels à la Monitor
classe. À quoi sert exactement le raccourci d'appel de verrouillage? Ou plus explicitement,
class LockVsMonitor
{
private readonly object LockObject = new object();
public void DoThreadSafeSomethingWithLock(Action action)
{
lock (LockObject)
{
action.Invoke();
}
}
public void DoThreadSafeSomethingWithMonitor(Action action)
{
// What goes here ?
}
}
Mise à jour
Merci à tous pour votre aide: j'ai posté une autre question en réponse à certaines des informations que vous avez toutes fournies. Puisque vous semblez bien connaître ce domaine, j'ai publié le lien: Quel est le problème avec cette solution pour verrouiller et gérer les exceptions verrouillées?
lock
bloc.Pulse
d'un simple verrouillage. C'est important dans certains scénarios de multi-threading avancés. Je ne l'ai jamais utiliséPulse
directement.lock
est juste un raccourci pourMonitor.Enter
avectry
+finally
etMonitor.Exit
. Utilisez l'instruction de verrouillage chaque fois que cela suffit - si vous avez besoin de quelque chose comme TryEnter, vous devrez utiliser Monitor.la source
Une instruction de verrouillage équivaut à:
Monitor.Enter(object); try { // Your code here... } finally { Monitor.Exit(object); }
Cependant, gardez à l'esprit que Monitor peut également Wait () et Pulse () , qui sont souvent utiles dans des situations de multithreading complexes.
Mise à jour
Cependant, en C # 4, il est implémenté différemment:
bool lockWasTaken = false; var temp = obj; try { Monitor.Enter(temp, ref lockWasTaken); //your code } finally { if (lockWasTaken) Monitor.Exit(temp); }
Merci à CodeInChaos pour les commentaires et les liens
la source
Monitor
est plus flexible. Mon cas d'utilisation préféré de l'utilisation du moniteur est lorsque vous ne voulez pas attendre votre tour et simplement sauter ://already executing? forget it, lets move on if(Monitor.TryEnter(_lockObject)) { //do stuff; Monitor.Exit(_lockObject); }
la source
Comme d'autres l'ont dit,
lock
est «équivalent» àMonitor.Enter(object); try { // Your code here... } finally { Monitor.Exit(object); }
Mais juste par curiosité,
lock
conservera la première référence que vous lui passerez et ne la lancera pas si vous la changez. Je sais qu'il n'est pas recommandé de changer l'objet verrouillé et que vous ne voulez pas le faire.Mais encore une fois, pour la science, cela fonctionne bien:
var lockObject = ""; var tasks = new List<Task>(); for (var i = 0; i < 10; i++) tasks.Add(Task.Run(() => { Thread.Sleep(250); lock (lockObject) { lockObject += "x"; } })); Task.WaitAll(tasks.ToArray());
... Et cela ne fait pas:
var lockObject = ""; var tasks = new List<Task>(); for (var i = 0; i < 10; i++) tasks.Add(Task.Run(() => { Thread.Sleep(250); Monitor.Enter(lockObject); try { lockObject += "x"; } finally { Monitor.Exit(lockObject); } })); Task.WaitAll(tasks.ToArray());
Erreur:
C'est parce que
Monitor.Exit(lockObject);
va agir surlockObject
ce qui a changé parce questrings
sont immuables, alors vous l'appelez à partir d'un bloc de code non synchronisé .. mais de toute façon. C'est juste un fait amusant.la source
object temp = lockObject; Monitor.Enter(temp); <...locked code...> Monitor.Exit(temp);
Les deux sont la même chose. lock est un mot-clé c sharp et utilise la classe Monitor.
http://msdn.microsoft.com/en-us/library/ms173179(v=vs.80).aspx
la source
Le verrouillage et le comportement de base du moniteur (entrée + sortie) sont plus ou moins les mêmes, mais le moniteur a plus d'options qui vous permettent plus de possibilités de synchronisation.
Le verrou est un raccourci, et c'est l'option pour l'utilisation de base.
Si vous avez besoin de plus de contrôle, le moniteur est la meilleure option. Vous pouvez utiliser Wait, TryEnter et Pulse, pour des usages avancés (comme les barrières, les sémaphores, etc.).
la source
Le mot clé Lock Lock garantit qu'un thread exécute un morceau de code à la fois.
lock (lockObject)
{ // Body }
Le mot clé lock marque un bloc d'instructions comme une section critique en obtenant le verrou d'exclusion mutuelle pour un objet donné, en exécutant une instruction puis en libérant le verrou
Si un autre thread essaie d'entrer un code verrouillé, il attendra, se bloque, jusqu'à ce que l'objet soit libéré.
Monitor Le moniteur est une classe statique et appartient à l'espace de noms System.Threading.
Il fournit un verrouillage exclusif sur l'objet afin qu'un seul thread puisse entrer dans la section critique à un moment donné.
Différence entre Monitor et Lock en C #
Le verrou est le raccourci pour Monitor.Entrez avec try et enfin. Les poignées de verrouillage essaient et enfin bloquent en interne Lock = Monitor + essayez enfin.
Si vous voulez plus de contrôle pour mettre en œuvre des solutions de multithreading avancées en utilisant
TryEnter()
Wait()
,Pulse()
et lesPulseAll()
méthodes, la classe Monitor est votre option.C #
Monitor.wait()
: un thread attend que d'autres threads soient notifiés.Monitor.pulse()
: Un thread notifie à un autre thread.Monitor.pulseAll()
: Un thread notifie tous les autres threads d'un processusla source
En plus de toutes les explications ci-dessus, lock est une instruction C # tandis que Monitor est une classe de .NET située dans l'espace de noms System.Threading.
la source