Um den Zugriff auf meine Eigenschaften zu synchronisieren, verwende ich die ReaderWriterLockSlim Klasse. Ich verwende den folgenden Code, um thread-sicher auf meine Eigenschaften zuzugreifen.Microsofts Bemerkung zu ReaderWriterLockSlim.IsReadLockHeld/IsWriteLockHeld und seine Folgen
public class SomeClass
{
public readonly ReaderWriterLockSlim SyncObj = new ReaderWriterLockSlim();
public string AProperty
{
get
{
if (SyncObj.IsReadLockHeld)
return ComplexGetterMethod();
SyncObj.EnterReadLock();
try
{
return ComplexGetterMethod();
}
finally
{
SyncObj.ExitReadLock();
}
}
set
{
if (SyncObj.IsWriteLockHeld)
ComplexSetterMethod(value);
else
{
SyncObj.EnterWriteLock();
ComplexSetterMethod(value);
SyncObj.ExitWriteLock();
}
}
}
// more properties here ...
private string ComplexGetterMethod()
{
// This method is not thread-safe and reads
// multiple values, calculates stuff, ect.
}
private void ComplexSetterMethod(string newValue)
{
// This method is not thread-safe and reads
// and writes multiple values.
}
}
// =====================================
public static SomeClass AClass = new SomeClass();
public void SomeMultiThreadFunction()
{
...
// access with locking from within the setter
AClass.AProperty = "new value";
...
// locking from outside of the class to increase performance
AClass.SyncObj.EnterWriteLock();
AClass.AProperty = "new value 2";
AClass.AnotherProperty = "...";
...
AClass.SyncObj.ExitWriteLock();
...
}
Um unnötige Sperren zu vermeiden, wenn ich mehrere Objekte einmal veröffentlichte ich die ReaderWriterLockSlim
-Object und sperren sie von außerhalb der Klasse jedes Mal, ich bin zu bekommen oder setzen eine Reihe von Eigenschaften und festlegen. Um dies zu erreichen, überprüfen meine Getter- und Setter-Methoden, ob das Schloss unter Verwendung der IsReadLockHeld
-Eigenschaft und der IsWriteLockHeld
-Eigenschaft von ReaderWriterLockSlim
erfasst wurde. Das funktioniert gut und hat die Leistung meines Codes erhöht.
So weit so gut, aber wenn ich die Dokumentation über IsReadLockHeld
und IsWriteLockHeld
ich die Bemerkung Form Microsoft bemerkte erneut lesen: ist
Diese Eigenschaft zur bestimmungsgemäßen Verwendung in behauptet oder für andere Zwecke Debuggen . Verwenden Sie es nicht, um den Ablauf der Programmausführung zu steuern.
Meine Frage ist: Gibt es einen Grund, warum sollte ich nicht IsReadLockHeld/IsWriteLockHeld
für diesen Zweck verwenden? Ist mit meinem Code etwas nicht in Ordnung? Alles funktioniert wie erwartet und viel schneller als rekursive Sperren (LockRecursionPolicy.SupportsRecursion
).
Um dies zu verdeutlichen: Dies ist ein minimales Beispiel. Ich will nicht wissen, ob das Schloss selbst notwendig ist oder entfernt oder auf andere Weise erreicht werden kann. Ich möchte nur wissen, warum ich IsReadLockHeld
/IsWriteLockHeld
nicht verwenden sollte, um den Programmablauf zu steuern, wie in der Dokumentation angegeben.
Der ReaderWriteLockSlim schützt nichts, .NET verspricht bereits, dass Objektreferenzaktualisierungen atomar sind. Der einzige milde Nebeneffekt ist, dass die Setter-Updates in anderen Threads sichtbar sind. Viel billiger, einfach MemoryBarrier() zu verwenden. Keine Thread-Sicherheitsgarantien wie auch immer, Sie sind sicher besser dran, SyncObj vollständig zu entfernen, da es nur ein falsches Gefühl der Sicherheit gibt. –
@EricLippert: Die Dokumente für 'IsRead/WriteLockHeld' schlagen vor, dass sie' true' zurückgeben, wenn der * aktuelle Thread * die Sperre hält. Wenn "IsRead/WriteLockHeld" den Wert "true" zurückgibt, wie kann der Sperrstatus in diesem Thread geändert werden, ohne explizit auf "ExitRead/WriteLock" zu verweisen? – Iridium
@Iridium: Ich ziehe meinen Kommentar zurück; Ich bin mir jetzt eigentlich nicht sicher, warum die Dokumentation diesen Vorbehalt macht. Das heißt: Best Practice ist zu tun, was die Dokumentation sagt. –