这个类线程安全吗?

2 c# multithreading

这个ValueStore类线程是否安全?GetInt(字符串键)中的锁定范围是否需要在yield return周围扩展?

public class ValueStore
{
  private readonly object _locker = new object();
  private readonly Dictionary<string, int> _data = 
    new Dictionary<string, int>();

  public ValueStore(Dictionary<string, int> data)
  {
    _data = data;
  }

  public IEnumerable<int> GetInt(string key)
  {
    IEnumerable<KeyValuePair<string, int>> selected;
    lock(_locker)
    {
      selected = _data.Where(x => x.Key.Equals(key));
    }

    foreach (KeyValuePair<string, int> pair in selected)
    {
      yield return pair.Value;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

单元测试似乎很好:

[TestFixture]
public class ValueStoreTest
{
  [Test]
  public void test1()
  {
    Dictionary<string, int> data = new Dictionary<string, int>();
    for (int i = 0; i < 100000; i++)
    {
      data.Add(i.ToString(),i);
    }

    ValueStore vs = new ValueStore(data);

    for (int i = 0; i < 900000; i++)
    {
      ThreadPool.QueueUserWorkItem(delegate
      {
        for (int j = 0; j < 100000; j++)
        {
          IEnumerable<int> d = vs.GetInt(j.ToString());
        }
      });
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 6

不,它绝对不是线程安全的.

它使用客户端传入的字典这一事实意味着您无法控制客户端何时更改它.您也只是在应用Where子句时锁定它- 但实际上根本不执行任何迭代.在迭代结果时你需要保持锁定 - 但正如我之前所说,它不会阻止客户端随时更改字典.

如果你在类中创建了字典并且只暴露了它中的数据(即保护它不受外界影响),你可以使它完全是线程安全的.如果您坚持客户端代码不会改变字典,则根本不需要锁定,因为当没有编写器时,字典可以安全地从多个线程读取.