多个线程能否完全同时将项目添加到并发集合中?

Can multiple threads add items to Concurrent collections EXACTLY at the same time?

我正在尝试找出 C# 中的并发集合。

ConcurrentBag、ConcurrentDictionary 和 ConcurrentQueue。

多个线程是否可以同时EXACTLY添加项目?还是他们一个接一个地等?

我试图检查他们的源代码,但我真的不能确定。

我看到 有 C++ 的答案,但我想知道 C# 是否也是这种情况?

从一般意义上讲,答案是加法是序列化的,即它们相互等待。

确切的机制取决于一系列条件,并且他们尽可能地尝试在没有锁的情况下进行(互锁交换而不是锁或互斥锁),但是有些路径需要锁(一目了然,例如,如果内部数组需要调整大小或者其他人正在请求同步枚举)。

在软件层面无法证明。这意味着您无法编写可以证明或反驳两个项目可以在同一集合中的两个线程同时插入的理论的程序。

一个证明它的尝试是让第三个线程充当观察者,它将在一个紧密的循环中重复枚举集合,而其他两个线程正在执行两个并发插入。假设观察者线程在一个枚举中观察到零个元素,在下一个枚举中观察到两个元素,这将证明什么?线程可以随时被操作系统挂起,持续时间以毫秒为单位,因此您还没有了解到关于手头问题的任何结论。这两个插入可能完全同时发生,或者彼此相隔几毫秒,谁知道呢?

如果要从硬件层面回答这个问题,那么在这个层面上不存在“采集”的概念。您有寄存器、CPU 指令、存储芯片等。在这个级别上没有可讨论的软件对象。

将对象添加到集合中不是一个简单的操作。这是 事件的 序列

事件可以同时发生,但当我们谈论事件序列时,序列要么重叠,,要么不相交。

计算机硬件的设计使得如果两个事件同时发生,结果总是就好像其中一个发生在另一个之前。原因很简单。假设线程A赋值v=3,假设线程B赋值v=5。如果线程A先走,最后的结果就是v==5。如果线程 B 先进行,则最终结果将是 v==3。没有程序员愿意处理第三种可能的结果。它甚至会是什么?

无论硬件发生什么,当我们在程序中谈论事件时,我们从不说“同时”。我们相信硬件的行为 就好像 这种可能性不存在。


当我们谈论重叠的操作序列(例如,将对象添加到某个集合)时,这是一个主要问题。这就是 concurrency control 的意义所在。

如果并发控制做得好,那么两个线程各自插入一个对象到一个集合中后,集合将保证包含这两个对象。如果它做错了,几乎任何事情都是可能的,(包括任何进一步尝试使用该集合的可能性都会使程序崩溃。)

您实际上可以花费 研究并发控制的所有不同方法。