【问题标题】:c++ Multithreading - how writes to a shared variable are handledc ++多线程-如何处理对共享变量的写入
【发布时间】:2021-03-15 15:16:20
【问题描述】:

正如标题所暗示的 - 在 C++ 中,如何处理线程中对共享变量的写入?线程是否使用它们自己的数据副本?我知道线程之间共享什么,什么不是,但我找不到关于在多线程场景中如何处理对变量的写入的任何信息。

让我给你一点背景。在 Java 中,线程处理它们自己的数据副本。我们添加同步以确保线程的写入对其他线程可见。简而言之,同步可确保将写入刷新到主内存。

类似的结构对 c/c++ 有效吗?如果一个线程正在写入一个变量,这些写入是否会立即更新到主内存,或者是操作系统控制如何写入主内存?我们是否需要添加同步来刷新这些更新?

例如如果两个线程正在递增一个计数器,我可以保证第一个线程总是首先完成该特定任务(不知何故,通过使用第二个线程的延迟启动,在实践中可能无法保证)并且不会有两个线程之间的任何指令混乱,那么我是否总是能看到两个线程的影响?

Thread 1 { i++; ... do something that takes long time}
Thread 2 { i++; ... do something that takes long time}

谢谢, RG

【问题讨论】:

  • 在 Java 中,线程不能处理它们自己的数据副本。在 Java 中,您需要同步以避免线程同时访问相同的数据,因为这样做会导致崩溃。这同样适用于 C++。
  • 请注意,您不使用任何同步,您可能很容易遇到在 C++ 中导致 未定义行为数据竞争。例如,i 的类型为 int 并且其增量不受互斥体保护时就是这种情况。如果istd::atomic<i> 类型,那么,你很好。

标签: c++ multithreading operating-system


【解决方案1】:

线程是否使用它们自己的数据副本?

不,除非数据声明为thread_local

同步确保写入刷新到主内存。 类似的构造对 c/c++ 有效吗?如果一个线程正在写入一个变量,这些写入是否会立即更新到主内存中

是的,但除非您使用某种同步,否则其他线程可能会或可能不会看到更改 - 或读取不正确。

我们是否需要添加同步来刷新这些更新?

是的,但我不确定我是否会使用冲洗这个词。 “同步”很好。

例如如果两个线程都在增加一个计数器,我可以保证第一个线程总是先完成......

如果你能保证,你就有同步。

我会一直看到这两个线程的影响吗?

是的,如果你有你所说的保证。

【讨论】:

  • 谢谢特德。从 link 开始,同步确保了对其他线程可见的内容。除非读取器和写入器使用同步,否则无法保证写入会变得可见。在 C++ 中,从我收集的信息来看,如果一个线程正在更新共享变量,当另一个线程查找它时,它对其他线程是可见的,而无需显式的同步构造。是这样吗?
  • @user14757101 不。正如我在答案中所写,如果没有同步,其他线程可能会也可能不会看到更新或看到“一半”。
  • 谢谢特德!是的,我不知何故错过了那个。
【解决方案2】:

C++ 不能保证读/写和刷新到内存的原子性如何工作,除非您使用原子原语,例如 std::atomic。在这里要非常小心。无锁编程很难做到正确。

我的建议是使用锁。

【讨论】:

  • 没错。如果您想确保在线程之间安全使用变量,您需要查看互斥锁或信号量 (faculty.cs.niu.edu/~hutchins/csci480/semaphor.htm)
  • @RussellIslam 为什么要使用非标准库? C++ 标准包含自 C++11 以来的互斥锁。
  • 感谢 Tumbleweed53!因此,除非互斥体或原子变量用于触发这些刷新,否则刷新对内存的更改由操作系统处理?
  • @user14757101 不仅仅是操作系统、CPU 和内存总线本身。使用 std::atomic 允许您 (a) 防止编译器重新排序您的内存读取和写入,(b) 确保读取和写入以原子方式完成并且不会分成多个部分,以及 (c) 确保处理器不会重新排序你的读写。后一部分(c)对于多处理器系统(基本上现在的每个系统)尤其重要。然而,即使理解和使用std::atomic API 也是一个真正的挑战,而且很容易产生错误。这只是一个硬域。这就是人们使用锁的原因。
猜你喜欢
  • 2013-05-23
  • 2019-12-11
  • 2020-06-12
  • 1970-01-01
  • 1970-01-01
  • 2013-06-26
  • 1970-01-01
  • 2016-02-09
  • 1970-01-01
相关资源
最近更新 更多