C# 如何正确使用readerwriterlock

C# 如何正确使用readerwriterlock,c#,.net,multithreading,readerwriterlock,C#,.net,Multithreading,Readerwriterlock,您好,我需要在我的方法中使用writerreaderlock。我想知道如何正确使用它 我有一本ObjectA词典 public class ObjectA { public ReaderWriterLock RWL {get;set;} public ObjectB obj {get;set;} public ObjectA() { RWL = new ReaderWriterLock(); } } public class Object

您好,我需要在我的方法中使用writerreaderlock。我想知道如何正确使用它

我有一本ObjectA词典

public class ObjectA
{
    public ReaderWriterLock RWL {get;set;}
    public ObjectB obj {get;set;}
    public ObjectA()
    {
        RWL = new ReaderWriterLock();
    }
}

public class ObjectB
{
    int TTL {get;set;}
    string Value {get;set;}
}
在我的方法中,我使用ObjectA字典,键是Guid,因此假设当我调用dict[Guid]时,它总是返回我的ObjectA实例(例如)

publicfoo()
{
ObjecA objA=dict[guid];
objA.RWL.EADERLOCK(500);

if(objA.obj.TTL此代码存在许多问题,包括:

  • 实际上,您从来没有在类实例中递减TTL——正如Nikolai指出的,您递减的是一个局部变量!
    Interlocked。递减(ref objA.obj.TTL)
    是如何正确地做到这一点的
  • 您没有设置初始TTL值,因此它将始终为零(除非其他一些代码正在设置它,这对于线程敏感类来说可能是不明智的,因为您通常希望所有线程安全相关代码都在同一个类中,以避免忘记谁在做什么)
  • 您应该使用,它现在比旧类更受欢迎。有关原因,请参阅后一个超链接
  • 在获取写锁时,如果您已经拥有读锁,则需要升级锁——在锁类上通常有一个单独的方法用于升级。类似地,升级后,释放锁需要一个方法来释放锁,而不是一个方法来释放写锁,另一个方法来释放以前的读锁
  • 您需要处理无法获取锁的故障情况
  • 您需要将代码封装在或块中,以确保即使发生异常也能释放资源
您是否真的需要使用读写器锁,而不是使用简单的锁,这也是值得考虑的。即使对于非常了解这些API和概念的开发人员来说,正确地获得读写器锁并避免死锁也是很困难的,即使这样,他们通常也会保留它们的使用,以获得最高的性能-关键位置(每秒1000个以上)。换句话说,您最好从使用
lock{}
的更简单方法开始,如果性能不可接受,只使用
readerwriterlocksim

作为起点,我建议您在问题中添加更多信息:

  • 首先,对您正在尝试做的事情进行高层次的描述,包括对功能和性能的高层次要求。这可以帮助我们推荐正确的解决方案,并了解读写器锁定是否是正确的方法
  • 试着用伪代码或简单的英语写出您希望代码的行为,包括您希望如何解决上面的逻辑问题(例如,发生超时时该怎么做,TTL是如何设置的,等等)
  • 修改您的代码示例,以包括我上面提到的部分/所有问题的修复

我向您保证,如果您在问题中包含此附加信息,您将得到更好的答案,这可以帮助您解决任何剩余的代码问题。:-)

这一点可以肯定的是,您没有正确地递减TTL。您自动递减堆栈变量,而不是类成员。感谢您的回答,但我展示的代码只是一个示例,我在HttpHandler中使用了我的代码,锁定对我的web应用程序来说确实太慢了。我将尝试使用ReaderWriterLockSlim。谢谢。我发现我可以升级我的应用程序readerlock到writerlock,这些信息将对我有所帮助。谢谢你的回答-非常有用!
public foo()
{
    ObjecA objA = dict[guid];
    objA.RWL.AcquireReaderLock(500);
    if(objA.obj.TTL<=0)
    {
        objA.obj.RWL.AcquireWriterLock(1000);
        objA.obj.Value = DateTime.Now().ToString();
        objA.obj.RWL.ReleaseWriterLock();
    }else{
         int ttl = objA.obj.TTL;
         Interlocked.Decrement(ref ttl);
    }    
    objA.RWL.ReleaseReaderLock();
}