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(); ... }
每当我收到或设置多个属性时,为了避免不必要的锁定,一旦我发布了ReaderWriterLockSlim-Object,并且每当我要获取或设置一堆属性时,它会从类外部锁定.为了达到这个目的,我的getter和setter方法检查是否已经使用IsReadLockHeld属性和ReaderWriterLockSlim的IsWriteLockHeld属性来获取锁.这工作正常,并增加了我的代码的性能.
到目前为止这么好,但是当我重新阅读有关IsReadLockHeld和IsWriteLockHeld的文档时,我注意到Microsoft的备注:
This property is intended for use in asserts or for other debugging
purposes. Do not use it to control the flow of program execution.
我的问题是:为什么我不应该使用IsReadLockHeld / IsWriteLockHeld为此目的?我的代码有什么问题吗?一切都按预期方式工作,比使用递归锁(LockRecursionPolicy.SupportsRecursion)快得多.
澄清一下:这是一个最小的例子.我不想知道锁本身是否必要或可以以不同的方式被删除或实现.我只是想知道为什么我不应该使用IsReadLockHeld / IsWriteLockHeld来控制程序的流程,如文档所述.
解决方法
I’m afraid my answer may leave something to be desired.
The property works fine and as documented. The guidance really is just
because conditional acquisition and release of locks tends to be buggy
and error-prone in practice,particularly with exceptions thrown into
the mix.It’s typically a good idea to structure your code so that you either
use recursive acquires,or you don’t,(and of course the latter is
always easier to reason about); using properties like IsReadLockHeld
lands you somewhere in the middle.I was one of the primary designers of RWLS and I have to admit it has
way too many bells and whistles. I don’t necessarily regret adding
IsReadLockHeld — as it can come in handy for debugging and assertions
— however as soon as we added it,Pandora’s Box was opened,and we RWLS was instantly opened up to this kind of usage.I’m not surprised that people want to use it as shown in the
StackOverflow thread,and I’m sure there are some legitimate scenarios
where it works better than the alternatives. I merely advise erring on
the side of not using it.
总结一下:您可以使用IsReadLockHeld和IsWriteLockHeld属性来有条件地获取锁定,一切都可以正常工作,但是编程风格不好,应避免使用.最好坚持递归或非递归锁.为了保持良好的编码风格,IsReadLockHeld和IsWriteLockHeld只能用于调试目的.
我要再次感谢马塞尔·罗马和乔·达菲的宝贵帮助.