2009-08-06 57 views
2

我在OLTP应用程序中遇到线程争用。在审查有关的代码,我发现:修改锁定块内的锁定对象

 lock (_pendingTransactions) 
     { 
      transaction.EndPointRequest.Request.Key = (string)MessageComparer.GenerateKey(transaction.EndPointRequest.Request); 

      if (!_pendingTransactions.ContainsKey(transaction.EndPointRequest.Request.Key)) 
      { 
       _pendingTransactions.Add(transaction.EndPointRequest.Request.Key, transaction); 

       return true; 
      } 
      else 
      { 
       return false; 
      } 
     } 

正如你可以在摘要中看到,有可能是“锁”块中修改的对象上的锁。那有什么不好吗?任何人都有这样的问题吗?

回答

3

以这种方式使用锁通常是不鼓励的,建议使用专用的锁定字段(类成员变量)。专用锁场Object型的,通常是这样的:

private object _pendingTransactionLock = new object(); 

如果对象本身具有一定的线程意识,这个锁变量可能在_pendingTransaction的实现类属。否则,它可能属于字段声明类中的_pendingTransaction

你不说什么类型_pendingTransaction是。如果这是一个提供SyncRoot属性的内置集合类,那么这可能是一个不错的选择。

请参阅Jon Skeet的“选择锁定什么”。

0

一般来说,人们会锁定一个对象,因为有人会修改(或读取)它,所以没有什么内在的错误。

0

也许密钥生成可以在锁定块之外进行,以减少锁定的持续时间。除此之外,这几乎是一个保护列表/集合/数组的锁定示例:获取锁定,检查密钥是否存在,如果尚未存在则添加密钥,释放锁定。