字典和锁 C# 的奇怪问题

本文关键字:问题 字典 | 更新日期: 2023-09-27 17:56:33

目前,我有一个关于锁定字典的非常奇怪的问题。我有两个不同的线程访问字典,一个线程输入一些条目,另一个线程尝试读出它们。在输入时一切都很好,当我尝试从字典中提取一些值时,最奇怪的问题发生了。

这是它的样子

 lock (myDictionary)
{
 //Add an entry here for a key.
}

检索

lock(myDictionary)
{
 if (myDictionary.ContainsKey(key))
 myDictionary.TryGetValue(key, out store);
}

一旦线程输入上述代码,就找不到密钥。但是如果我写以下内容

lock(myDictionary)
{
  Console.WriteLine(myDicionary.Count)
 if (myDictionary.ContainsKey(key))
   myDictionary.TryGetValue(key, out store);
}

我突然看到同一个字典,其中包含在以前的代码中找不到的键。现在你们可以争辩说,发生的事情是 I/O 延迟导致字典有足够的时间来存储一些值,但我没有任何超时或导致我丢失任何处理的东西,这意味着什么直到字典包含一些要提取的值,下一个处理步骤不会发生,我的程序将等到它获得一些值。但不幸的是,除非我放一个 Console.WriteLine...以前有人遇到过这种情况吗?

字典和锁 C# 的奇怪问题

问题很可能出在您未显示的代码中。您描述的问题类型在多线程方案中非常常见:一切都归结为计时,当您稍微更改代码时,计时会有所不同。在您的特定情况下,您尝试访问的任何值都存在或不存在,具体取决于其他线程中发生的时间。当您的代码找不到它时,该值可能尚未放置或已被删除,但当您的代码看不到它时,该值仍然存在。

如果不看到代码的其余部分,尤其是向集合写入/删除的部分,就不可能肯定地说。

其他几件事:

  • 您需要锁定读写访问权限
  • 即使您同时锁定了读取和写入访问权限,也无法保证某个对象存在,除非您还使用其他类型的同步
  • 正如其他人所说,将ContainsKeyTryGetValue结合使用没有多大意义,你写它的方式。"TryGetValue"的存在是为了让你不需要调用ContainsKey:如果值在那里,它将立即返回给你,如果不是,方法调用的结果会告诉你这一点。