简体   繁体   English

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

[英]multithreading: lock on property - is this correct?

I have written the following code: 我写了以下代码:

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);
    }
}

QUESTION : 问题
Is this a correct manner to safely add the failed test to the Dictionary? 这是将失败的测试安全地添加到字典中的正确方法吗?
Is this threadsafe? 这线程安全吗?
Is FailedTests.Add called INSIDE the lock or OUTSIDE the lock? 是FailedTests.Add调用INSIDE锁定还是OUTSIDE锁定?

Can you explain why this is correct/threadsafe or why not? 你能解释为什么这是正确的/线程安全的,或者为什么不呢?

Thanks in advance 提前致谢

The fundamental problem with the code above is that it only locks access to _failedTests when a thread is getting the dictionary or setting it. 上面代码的基本问题是,当线程获取字典或设置字典时,它只锁定对_failedTests访问。 Only one thread can get a reference to the dictionary at a time, but once a thread has a reference to the dictionary, it can read and manipulate it without being constrained by locks. 只有一个线程可以一次获得对字典的引用,但是一旦线程具有对字典的引用,它就可以读取和操作它而不受锁的约束。

Is this a correct manner to safely add the failed test to the Dictionary? 这是将失败的测试安全地添加到字典中的正确方法吗?

No, not if two threads are trying to add to the dictionary at the same time. 不,如果两个线程同时尝试添加到字典中,请不要这样做。 Nor if you expect reads and writes to happen in a particular order. 如果您希望读取和写入按特定顺序发生,也不会发生。

Is this threadsafe? 这线程安全吗?

It depends what you mean by threadsafe , but no, not by any reasonable definition. 这取决于你对线程安全的意思 ,但不是,不是任何合理的定义。

Is FailedTests.Add called INSIDE the lock or OUTSIDE the lock? 是FailedTests.Add调用INSIDE锁定还是OUTSIDE锁定?

The dictionary retrieval (the get accessor) happens inside a lock. 字典检索( get访问器)发生在锁内。 This code calls Add after releasing the lock. 此代码在释放锁之后调用Add

Can you explain why this is correct/threadsafe or why not? 你能解释为什么这是正确的/线程安全的,或者为什么不呢?

If multiple threads operate on your dictionary at the same time, you can't predict the order in which those threads will change its contents and you can't control when reads will occur. 如果多个线程同时在您的字典上运行,则无法预测这些线程将更改其内容的顺序,并且您无法控制何时将进行读取。

This is not thread-safe access to a dictionary, because only the property access that returns the dictionary object is thread-safe, but you are not synchronizing the call to the Add method. 这不是对字典的线程安全访问,因为只有返回字典对象的属性访问是线程安全的,但是您没有将调用同步到Add方法。 Consider using ConcurrentDictionary<string,Exception> in this case, or synchronize calls to Add manually. 在这种情况下,请考虑使用ConcurrentDictionary<string,Exception> ,或者手动将调用同步到Add

I don;t thinks this is threadsafe, because the lock is kept only in the very brief moment where the pointer to the collection is returned. 我不认为这是线程安全的,因为锁定只保留在返回指向集合的指针的非常短暂的时刻。 When you Add to the collection there is no lock so if two threads try to add at the same time you'll get a nasty error. 当您添加到集合时没有锁定,所以如果两个线程同时尝试添加,您将收到一个讨厌的错误。 So you should lock around the FailedTest.Add code. 所以你应该锁定FailedTest.Add代码。

You may also want to look into concurrent collections, they might provide what you need. 您可能还想查看并发集合,它们可能会提供您所需的内容。

Regards GJ 关心GJ

The call to Add() is outside the locks. Add()的调用在锁外。

You can solve it by writing your own Add() method to replace the property. 您可以通过编写自己的Add()方法来替换属性来解决它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM