修改锁定块中的锁定对象

时间:2009-08-06 03:58:46

标签: c# synchronization thread-safety

我在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 个答案:

答案 0 :(得分:3)

通常不建议以这种方式使用锁定,建议使用专用锁定字段(类成员变量)。专用锁定字段的类型为Object,通常如下所示:

private object _pendingTransactionLock = new object();

如果对象本身具有一些线程感知,则此锁定变量可能属于_pendingTransaction的实现类。否则,它可能属于该字段的声明类中的_pendingTransaction

您没有说明_pendingTransaction是什么类型。如果这是一个提供SyncRoot属性的内置集合类,那么这可能是一个很好的选择。

见Jon Skeet选择锁定什么。

答案 1 :(得分:0)

一般来说,一个人会专门锁定一个对象,因为一个人会修改(或读取)它,所以这没有任何内在错误。

答案 2 :(得分:0)

可能会在锁定块外部生成密钥生成,以减少锁定的持续时间。除此之外,这是一个几乎规范的锁定示例,用于保护列表/集合/数组:获取锁定,检查密钥是否存在,添加密钥(如果尚未存在),释放锁定。