我在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;
}
}
正如您在代码段中看到的那样,在“锁定”块中修改的对象上存在锁定。这有什么不好的吗?有人在做这样的事情时遇到了问题吗?
答案 0 :(得分:3)
通常不建议以这种方式使用锁定,建议使用专用锁定字段(类成员变量)。专用锁定字段的类型为Object
,通常如下所示:
private object _pendingTransactionLock = new object();
如果对象本身具有一些线程感知,则此锁定变量可能属于_pendingTransaction
的实现类。否则,它可能属于该字段的声明类中的_pendingTransaction
。
您没有说明_pendingTransaction
是什么类型。如果这是一个提供SyncRoot
属性的内置集合类,那么这可能是一个很好的选择。
见Jon Skeet选择锁定什么。
答案 1 :(得分:0)
一般来说,一个人会专门锁定一个对象,因为一个人会修改(或读取)它,所以这没有任何内在错误。
答案 2 :(得分:0)
可能会在锁定块外部生成密钥生成,以减少锁定的持续时间。除此之外,这是一个几乎规范的锁定示例,用于保护列表/集合/数组:获取锁定,检查密钥是否存在,添加密钥(如果尚未存在),释放锁定。