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属性来获取锁.这工作正常,并增加了我的代码的性能.@H_301_5@
到目前为止这么好,但是当我重新阅读有关IsReadLockHeld和IsWriteLockHeld的文档时,我注意到Microsoft的备注:@H_301_5@
This property is intended for use in asserts or for other debugging
purposes. Do not use it to control the flow of program execution.@H_301_5@
我的问题是:为什么我不应该使用IsReadLockHeld / IsWriteLockHeld为此目的?我的代码有什么问题吗?一切都按预期方式工作,比使用递归锁(LockRecursionPolicy.SupportsRecursion)快得多.@H_301_5@
澄清一下:这是一个最小的例子.我不想知道锁本身是否必要或可以以不同的方式被删除或实现.我只是想知道为什么我不应该使用IsReadLockHeld / IsWriteLockHeld来控制程序的流程,如文档所述.@H_301_5@
解决方法
I’m afraid my answer may leave something to be desired.@H_301_5@
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.@H_301_5@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.@H_301_5@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.@H_301_5@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.@H_301_5@
总结一下:您可以使用IsReadLockHeld和IsWriteLockHeld属性来有条件地获取锁定,一切都可以正常工作,但是编程风格不好,应避免使用.最好坚持递归或非递归锁.为了保持良好的编码风格,IsReadLockHeld和IsWriteLockHeld只能用于调试目的.@H_301_5@
我要再次感谢马塞尔·罗马和乔·达菲的宝贵帮助.@H_301_5@