我写了以下代码:
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锁?
你能解释为什么这是正确的/线程安全的,为什么不呢?
提前致谢
答案 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()方法来替换属性来解决此问题。