C#这个方法线程安全吗?

use*_*346 8 c# multithreading

请考虑以下代码:

Dictionary<string, string> list = new Dictionary<string, string>();
object lockObj = new object();

public void MyMethod(string a) {

    if (list.Contains(a))
        return;

    lock (lockObj) {
        list.Add(a,"someothervalue");
    }
}
Run Code Online (Sandbox Code Playgroud)

假设我MyMethod("mystring")同时从不同的线程调用.

是否可能有多个线程(我们只需将其作为两个)同时输入if (!list.Contains(a))语句(具有几个CPU周期差异),两个线程都被评估为false,一个线程进入关键区域而另一个线程进入关键区域被锁定在外面,所以第二个线程进入并"mystring"在第一个线程退出后再次添加到列表中,导致字典尝试添加重复键?

Dav*_*rno 18

不,它不是线程安全的.你需要锁定list.Contains它,因为在if测试和添加数据之间可以切换一个线程并再次返回.另一个线程可能同时添加了数据.


Dus*_*gen 11

您需要锁定整个操作(检查并添加),否则多个线程可能会尝试添加相同的值.

线程时间轴

我建议使用ConcurrentDictionary(TKey, TValue)它,因为它被设计为线程安全.

private readonly ConcurrentDictionary<string, string> _items
    = new ConcurrentDictionary<string, string>();

public void MyMethod(string item, string value)
{
    _items.AddOrUpdate(item, value, (i, v) => value);
}
Run Code Online (Sandbox Code Playgroud)