C# C语言中关于线程的文档中的一个歧义#

C# C语言中关于线程的文档中的一个歧义#,c#,multithreading,thread-safety,C#,Multithreading,Thread Safety,在阅读乔·阿尔巴哈里(Joe Albahari)的优秀著作《C#中的线程技术》(Threading in C#)时,我遇到了以下模棱两可的句子: 线程安全类型不一定使使用它的程序成为线程安全的,后者所涉及的工作通常使前者成为冗余的 (您可以在上找到该句子;只需搜索“不确定性”即可快速跳转到相应的部分。) 我希望使用ConcurrentDictionary来实现某些线程安全的数据结构。这一段是否告诉我ConcurrentDictionary不能保证对数据结构的线程安全写入?有人能提供一个反例,说明

在阅读乔·阿尔巴哈里(Joe Albahari)的优秀著作《C#中的线程技术》(Threading in C#)时,我遇到了以下模棱两可的句子:

线程安全类型不一定使使用它的程序成为线程安全的,后者所涉及的工作通常使前者成为冗余的

(您可以在上找到该句子;只需搜索“不确定性”即可快速跳转到相应的部分。)

我希望使用ConcurrentDictionary来实现某些线程安全的数据结构。这一段是否告诉我ConcurrentDictionary不能保证对数据结构的线程安全写入?有人能提供一个反例,说明线程安全类型实际上无法提供线程安全吗


提前感谢您的帮助。

我对警告的理解是,仅仅因为您使用的是线程安全变量并不意味着您的程序是线程安全的


作为一个例子,考虑一个具有两个变量的类,该变量可以从两个线程中修改。仅仅因为这些变量是单独的线程安全的,并不能保证类修改的原子性。如果有两个线程修改这些变量,那么一个变量可能会以一个线程设置的值结束,而另一个变量则由另一个线程设置。这很容易破坏类的内部一致性。

我认为他的意思是,仅仅使用
ConcurrentDictionary
而不是
Dictionary
无处不在,并不会使程序线程安全。所以,如果你有一个非线程安全的程序,搜索和替换是没有帮助的;同样,在任何地方添加
SynchronizedAttribute
也不会像魔法仙子一样奏效。对于集合来说尤其如此,迭代总是一个问题[1]

另一方面,如果将非线程安全的程序重新构造为更线程安全的设计,则通常不需要线程安全的数据结构。一种流行的方法是根据相互发送“消息”的“参与者”来重新定义程序——除了单个生产者/消费者样式的消息队列之外,每个参与者都可以独立运行,不需要在内部使用线程安全的数据结构


[1] BCL集合的第一个版本包括一些“线程安全”集合,这些集合在迭代过程中不是线程安全的。并发集合在迭代期间是线程安全的,但与其他线程的修改同时迭代。其他集合库允许对“快照”进行迭代,忽略其他线程的修改。

最简单的情况是,线程安全列表或字典就是一个很好的例子;让每个操作都是线程安全的并不总是足够的—例如,“检查列表是否为空;如果为空,则添加一项”-即使所有操作都是线程安全的,也不能执行以下操作:

if(list.Count == 0) list.Add(foo);

因为它可能在两者之间发生变化。你需要同步测试<强>和Rechange。

< P>这是一个含糊的陈述,但是例如,考虑一个类有两个成员,每个成员都是线程安全的,但是这两个成员都必须以原子方式更新。

在处理这种情况时,您可能会使整个操作原子化,从而使线程安全,从而使对单个成员的线程安全访问变得无关紧要


If并不意味着您的ConcurrentDictionary将以不安全的方式运行。

前一段时间正在进行搜索,以解决我遇到的线程问题,并看到以下页面:

特别是“线程安全对象周围的锁定”部分

从页面:

有时还需要锁定访问线程安全对象的权限。为了举例说明,假设框架的List类确实是线程安全的,我们想向列表中添加一项:

不管这个列表是否是线程安全的,这个语句肯定不是


我的简明解释是这样的。线程安全有多种形式,满足一种形式的代码不会自动满足所有其他形式的代码。

Roy

我猜你“过度阅读”了一个太简洁的句子。。。我认为这句话有两个意思:

  • “仅仅使用threadsafe数据结构并不意味着你的程序可以正确处理多线程……正如threadsafe数据结构的存在本质上会使你的程序多线程一样”;然后他接着说
  • 除非你准备好投入其中(通常需要对相当复杂的场景有非常精确的理解)以使你的整个程序正确地处理线程,否则使用线程安全的数据结构基本上是浪费时间
  • 因此:多线程是相当困难的,使用合适的开箱即用数据结构是任何解决方案的重要组成部分,但它肯定不是整个解决方案……除非你准备仔细考虑(例如,在家里进行同步),否则你只是在开玩笑说数据结构会神奇地“修复”“你的计划

    我知道这听起来“有点刺耳”,但我的感觉是,当许多noob发现编程(尽管如此,在这个动漫图标和GUI画家的启蒙时代)需要深入思考时,他们真的很失望。谁会砰的一声

    干杯。基思

    这段话告诉我了吗 ConcurrentDictionary没有 保证线程安全写入到我的 数据结构

    不,乔·阿尔巴哈里不是这个意思
    ConcurrentDictionary
    将始终通过从多个线程同时写入来保持一致的状态。另一个线程永远不会看到数据结构处于不一致状态

    有人能提供一个 反例显示了一个 线程安全类型实际上无法 提供线程安全性

    但是,从线程安全类型进行的一系列读写操作仍然可能会失败
    if (!_list.Contains (newItem)) _list.Add (newItem);
    
    void ExecutedByMultipleThreads(ConcurrentQueue<object> queue)
    {
      object value;
      if (!queue.IsEmpty)
      {
        queue.TryDequeue(out value);
        Console.WriteLine(value.GetHashCode());
      }
    }