多线程:锁定属性 - 这是正确的吗?

时间:2011-01-31 14:49:21

标签: c# multithreading properties locking

我写了以下代码:

static readonly object failedTestLock = new object();

public static Dictionary<string, Exception> FailedTests
{
    get
    {
        lock (failedTestLock)
        {
            return _failedTests;
        }
    }
    set
    {
        lock (failedTestLock)
        {
            _failedTests = value;
        }
    }
}

public void RunTest(string testName)
{
    try
    {
        //Run a test
    }
    catch (Exception exception)
    {
        // ?? Is this correct / threadsafe?
        FailedTests.Add(testName, exception);
    }
}

问题
这是将失败的测试安全地添加到字典中的正确方法吗? 这线程安全吗? FailedTests.Add是锁定INSIDE还是OUTSIDE锁?

你能解释为什么这是正确的/线程安全的,为什么不呢?

提前致谢

4 个答案:

答案 0 :(得分:9)

上面代码的基本问题是,当线程获取字典或设置字典时,它只锁定对_failedTests的访问。一次只有一个线程可以获得对字典的引用,但是一旦线程具有对字典的引用,它就可以读取和操作它而不受锁的限制。

  

这是安全添加的正确方式吗?   字典失败的测试?

不,如果两个线程同时尝试添加到字典中则不行。如果您希望读取和写入按特定顺序发生,也不会。

  

这线程安全吗?

It depends what you mean by threadsafe,但不是,没有任何合理的定义。

  

FailedTests.Add是否被调用为INSIDE   锁定还是锁定外?

字典检索(get访问者)在锁内发生。释放锁后,此代码调用Add

  

你能解释为什么这是正确的/线程安全的,为什么不呢?

如果多个线程同时在您的字典上运行,则无法预测这些线程将更改其内容的顺序,并且您无法控制何时将进行读取。

答案 1 :(得分:7)

这不是对字典的线程安全访问,因为只有返回字典对象的属性访问是线程安全的,但是您没有将调用同步到Add方法。在这种情况下,请考虑使用ConcurrentDictionary<string,Exception>,或手动将呼叫同步到Add

答案 2 :(得分:2)

我不认为这是线程安全的,因为只在非常短暂的时刻保持锁定,返回指向集合的指针。当您添加到集合时没有锁定,所以如果两个线程同时尝试添加,您将收到一个讨厌的错误。 所以你应该锁定FailedTest.Add代码。

您可能还想查看并发集合,它们可能会提供您所需的内容。

关心GJ

答案 3 :(得分:2)

Add()的调用不在锁定范围内。

您可以通过编写自己的Add()方法来替换属性来解决此问题。