提问者:小点点

同时写入一次和读取多次…没有锁定[关闭]


这是一个关于一个作者和多个同时的读者的问题。

我希望这会激怒一些羽毛,我可能会因为胆敢问这个问题而被否决,但我想知道它是如何运作的。我知道互斥和原子是什么,没必要教我。

假设我有一个可供多个线程访问的内存位置(一个全局变量,或者我共享的一个指针)它的大小与体系结构相同,假设它是64位系统中8字节大小的单个无符号整数。它被设置为0

假设我有一千个线程在循环中读取它。如果它的0他们做一些重要的事情,如果它的1他们做另一件重要的事情,如果它既不0也不1他们发射核导弹。

然后一个线程(正好是一个,而不是多个)用值1覆盖此内存位置。会发生什么?

参见...我的理论是没有坏事发生,这是好的。没有数据损坏。在01之间没有半路。一个循环显示0,下一个循环显示1。不需要互斥或原子。我说的对吗?如果不是,为什么?

编辑:系统要求我解释为什么这和另一个问题不一样。答案是因为它和那个问题不一样。如果你不确定它有什么不同,请再读一遍,特别是以问号结尾的部分。


共2个答案

匿名用户

然后一个线程(正好是一个,而不是多个)用值1覆盖这个内存位置。会发生什么?

参见...我的理论是没有坏事发生,这是好的

你搞错了。

如果一个线程写入一个内存位置,而您没有任何同步机制,也没有使用原子,那么您就无法保证其他线程会看到更改。

variable=1;下运行着一整堆技术,几乎每一层都可以吞噬这个更新。

在程序集级别和CPU级别,不存在强制从1级缓存写回主内存的情况。

如果你只有一个变量和一个变化,这也不是太糟。有些线程会看到更新的值,有些则不会。更新传播可能需要很长的时间。你仍然可以称之为最终的一致性。

但一旦有了两个变量,写入值和读取值之间就会出现不一致。

把“内存模型一致性C++”放在你最喜欢的搜索引擎中了解更多细节。

匿名用户

线程通常不直接从内存读/写,而是读/写到它们的缓存。缓存是一个较小但速度快得多的内存。

要让一个读取器线程读取1而不是0,首先需要执行两件事:

  1. 写入程序线程必须已将其缓存写回内存。
  2. 读取器线程必须已从内存重新加载其缓存。

这些事件何时发生,取决于体系结构、OS、其他进程和您的代码。

您的每个读取器线程将读取0直到它们读取1。从0到1的切换可能根本不会发生,它可能发生在不同的线程的不同时间。

这就是原子的作用,它们可以在不同线程的缓存中强制同步。