2012-07-17 15 views
19

ich die folgende Sperre Aussage haben:Soll eine Sperrvariable als flüchtig deklariert werden?

private readonly object ownerLock_ = new object(); 

lock (ownerLock_) 
{ 
} 

Sollte ich volatile Schlüsselwort für meine Sperrvariable?

private readonly volatile object ownerLock_ = new object(); 

Auf MSDN sah ich, dass es in der Regel für ein Feld verwendet, die ohne Verriegelung zugegriffen wird, also wenn ich sperren verwenden Ich brauche nicht flüchtig zu benutzen?

Von MSDN:

Der flüchtige Modifikator wird in der Regel für ein Feld verwendet, die von mehrere Threads ohne Verwendung der lock-Anweisung zugegriffen wird, Zugang zu serialisieren.

+0

Wir brauchen viel mehr Kontext als das, um die Frage zu beantworten. Wo besteht dieses Schloss in Bezug auf die Objekte, die das Schloss benutzen? –

+3

Es ist definitiv Thread-Safe, wie es derzeit existiert. Keine Garantie wird möglich sein, wenn Sie Code innerhalb des Blocks sperren {} hinzufügen. –

+0

Sie sollten kein 'readonly'-Objekt sperren müssen ... in dem es' readonly' ist ... – NominSim

Antwort

18

Wenn Sie nur immer Zugriff auf die Daten, dass die Sperre „Wächter“ sind, während Sie die Sperre besitzen, dann ja - machen diese Felder flüchtigen überflüssig. Sie müssen die ownerLock_ Variable nicht flüchtig machen. (Sie haben derzeit keinen tatsächlichen Code in der lock-Anweisung gezeigt, was es schwer macht, konkret zu sprechen - aber ich nehme an, Sie würden tatsächlich lesen/ändern einige Daten innerhalb der lock-Anweisung.)

volatile sollte sehr selten im Anwendungscode verwendet werden. Wenn Sie einen lockfreien Zugriff auf eine einzelne Variable wünschen, ist Interlocked fast immer einfacher zu verstehen. Wenn Sie darüber hinaus einen gesperrten Zugriff wünschen, würde ich fast immer mit der Sperrung beginnen. (Oder versuchen Sie unveränderliche Datenstrukturen zu beginnen mit.)

Ich würde nur erwarten, volatile in Code zu sehen, der versucht, Abstraktionen höherer Ebene für Threading zu bauen - also zum Beispiel in der TPL-Codebasis. Es ist wirklich ein Werkzeug für Experten, die wirklich das .NET-Speichermodell gründlich verstehen ... von denen es sehr wenige gibt, IMO.

+0

Vielen Dank für Ihre schnelle Antwort, Lets sagen, ich benutze nur Lock, scheint es selten, aber können 2 Threads, die auf die Lock-Anweisung kommen beide OwnerLock_ Zustand gleichzeitig überprüfen und versuchen, es oder einander zu sperren? Ich stelle diese Frage, weil ich Probleme mit dem Sperren meines Codes hatte und ich denke, dass es sich um dieses Problem handelt. –

+0

@DorCohen: Nur einer von ihnen wird die Sperre zu einem Zeitpunkt erwerben. Es führt dann den Rumpf der 'lock'-Anweisung aus, und wenn er die Sperre aufhebt, kann der andere Thread die Sperre übernehmen und den Code ausführen. –

+0

@DorCohen, es scheint, dass Ihr Problem nicht darin besteht, was Sie sperren, sondern was Sie innerhalb des Sperrkörpers zu tun versuchen. –

2

Wenn etwas readonly ist, ist es Thread-sicher, Punkt. (Nun, fast. Ein Experte könnte in der Lage sein herauszufinden, wie eine NullReferenceException auf Ihrem lock-Anweisung zu bekommen, aber es wäre nicht einfach.) Mit readonly Sie brauchen nicht volatile, Interlocked, oder Sperren. Es ist das ideale Schlüsselwort für Multithreading, und Sie sollten es verwenden, wo immer Sie können. Es funktioniert gut für ein Lock-Objekt, wo sein großer Nachteil (Sie können den Wert nicht ändern) spielt keine Rolle.

Auch wenn die Referenz unveränderlich ist, ist das Objekt, auf das verwiesen wird, möglicherweise nicht. "new object()" ist hier, aber wenn es ein List oder etwas anderes änderbar - und nicht Thread-sicher - Sie wäre wollen, um die Referenz (und alle anderen Verweise darauf, falls vorhanden) zu sperren Das Objekt ändert sich in zwei Threads gleichzeitig.

Verwandte Themen