c# - 使用MemoryBarrier传播Dictionary <int,T>多线程应用程序中的更改

标签 c# multithreading dictionary

我有一个.NET 3.5应用程序,其中在两个线程之间共享一个Dictionary实例。我知道字典本身在任何方面都不是线程安全的,但是我只有一个线程可以修改字典,而另一个线程只需要确保执行工作时具有最新值即可。 (从最严格的意义上讲,即使是最新的也不是硬性要求)

一个线程正在接收间歇性的串行数据,并调用Set函数来更改字典中的值。 (此字典在初始设置后是固定大小的,我基本上只是将其用作稀疏数组)

第二个线程收集当前存储在字典中的值,并通过GetLatestValues()对它们进行一些处理。

public class HwMemoryMap{
   Dictionary<int, HwDataItem> HwCache;

   public void Set(HwDataItem dataItem){
       HwCache[dataItem.PtId] = dataItem;
       MemoryBarrier();
   }

   public List<HwDataItem> GetLatestValues(){
       System.Threading.Thread.MemoryBarrier();
       List<HwDataItem> HwDataItemList = new List<HwDataItem>();
       // do work here to pull appropriate values out of HwCache
       HwDataItemList.Add(HwCache[0]); // etc
       return HwDataItemList;
   }
}

是否在这里调用MemoryBarrier()足以确保对特定键的字典值的更改在所有线程/核心之间传播?

我的测试没有发现任何问题,但是考虑到这些问题的性质,这并不能给我带来任何安慰。

最佳答案

不,这不安全。您仍然冒着同时读写数据结构的风险。如果写入次数很少,您可以使用一个技巧,该技巧效果很好。基本上,您可以确保HwCache引用的数据结构保持不变。每次您想更改数据结构时,都首先将其复制到新实例中,然后在独占锁中更改新实例。然后,完成更改后,将HwCache引用换成新实例。为了使其正常工作,您必须将HwCache标记为volatile

public class HwMemoryMap
{
  private object lockobj = new object();
  volatile Dictionary<int, HwDataItem> HwCache;

  public void Set(HwDataItem dataItem)
  {
    lock (lockobj)
    {
      var copy = new Dictionary<int, HWDataItem>(HwCache);
      copy[dataItem.PtId] = dataItem;
      HwCache = copy;
    }
  }

  public List<HwDataItem> GetLatestValues()
  {
    var local = HwCache;
    var HwDataItemList = new List<HwDataItem>();
    // do work here to pull appropriate values out of local
    HwDataItemList.Add(local[0]); // etc
    return HwDataItemList;
  }
}

关于c# - 使用MemoryBarrier传播Dictionary <int,T>多线程应用程序中的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10098697/

相关文章:

c++ - 一个线程写入的值是否保证在不锁定该变量的情况下被另一个线程看到?

Python 求和字典列表中元组中的值?

c# - C 使用正则表达式快速搜索文件夹

java - 所有任务完成后spring boot应用程序不退出

c++ - 条件变量 POSIX 线程 : C/C++

python-3.x - 如何根据特定列对列表字典进行排序?

swift - handleWatchKitExtentionRequest ...如何访问回复元素以将值返回给 watchkit 扩展?

c# - 从文件夹读取文本文件时,给定路径不支持错误消息

c# - 使用 EnvDTE 程序集

c# - 根据调度程序将 async-await C# 代码转换为 F#