2

您好,我需要在我的方法中使用 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 的实例(例如)

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();
}

我真的不确定我在那里使用读写器,我需要如何使用读写器锁,有条件验证?

4

1 回答 1

6

这段代码有很多问题,包括:

  • 你实际上并没有在你的类实例中减少 TTL - 正如 Nikolai 指出的那样,你正在减少一个局部变量!Interlocked.Decrement(ref objA.obj.TTL)是如何正确地做到这一点。
  • 您没有设置初始 TTL 值,因此它将始终为零(除非其他一些代码正在设置它,这对于通常希望所有线程安全相关代码在同一线程敏感类中可能是不明智的上课以避免忘记谁在做什么)
  • 您应该使用ReaderWriterLockSlim,它现在比旧的ReaderWriterLock类更受欢迎。有关原因,请参见后一个超链接。
  • 获取写锁时,如果您已经拥有读锁,则需要升级锁——通常在锁类上有一个单独的方法。同样,升级后,释放锁需要一种方法来释放锁,而不是一种释放写锁和另一种释放之前的读锁的方法。
  • 您需要处理无法获取锁的失败情况。
  • 您需要将代码包装在usingtry/finally块中,以确保即使发生异常也能释放资源。

也可能值得考虑您是否真的,真的需要使用读/写锁,而不是使用像lock{}语句这样更简单的东西。即使对于非常了解这些 API 和概念的开发人员来说,获得正确的读取器/写入器锁并避免死锁也很困难,即便如此,他们通常只将其用于性能最关键的地方(每秒 1000 次以上)。换句话说,您最好从使用更简单的方法开始,并且只有在性能不可接受lock{}时才回退使用。ReaderWriterLockSlim

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

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

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

于 2009-11-04T18:00:42.140 回答