【问题标题】:With C++ concurrency, do I need to use mutual exclusion?使用 C++ 并发,我需要使用互斥吗?
【发布时间】:2012-08-03 19:28:35
【问题描述】:

我必须设计一个从本地网络读取 UDP 数据并将数据存储在当前值表 (CVT) 中的应用程序。

然后,一个单独的线程将出现并从 CVT 中读取值,对它们进行处理,然后通过 UDP 将它们发送出去。 CVT 条目将由单独的标量组成,例如浮点数和整数。

我的问题是,我需要多少互斥来保护 CVT 的更新/读取?

换句话说,如果我有一个线程写入 32 位 int 并且另一个线程从该 int 读取,我是否需要为此使用互斥锁?

我不在乎阅读器线程是否没有获得存储的绝对最新值,我只关心在更改该位置时尝试读取该位置。我知道关键字“volatile”在 Java 中用于这种情况,但在 C++ 中却没有做同样的事情。

【问题讨论】:

  • “我知道关键字“volatile”在 Java 中用于此场景,但在 C++ 中却没有做同样的事情。”谢谢你。 _o/\_
  • @GManNickG 你会欢迎 Obvious 船长上台吗?
  • @DesmondHume 不要把我拖进去;)

标签: c++ multithreading thread-safety mutex


【解决方案1】:

这在很大程度上取决于您使用哪种平台来支持线程。如果您有可用的原子类型,则可以使用它们。否则,是的,你几乎被一个互斥锁(某种类型的——许多平台有不止一种类型)卡住了。

【讨论】:

  • 有趣。请详细说明“原子类型”。一个字节?该平台只是 Windows 7 的 64 位版本。我猜也可能是 32 位 XP 和某些点。在我看来,float 或 int 或 double 不会在内存中原子地被修改。
  • 在 Intel x86 处理器上,以 32 位对齐方式读取和写入 32 位对象是原子的。 C++11 还添加了一个包含原子加载和存储的atomic 类。如果您的编译器支持它,我通常更喜欢后者。
【解决方案2】:

正如您描述的这个问题,只要您只有一个写入器,它就已经是线程安全的(假设代码在 32 位或更高字宽的处理器上运行 - 在这种情况下,32 位写入是原子的)。

volatile 存储修饰符告诉编译器变量具有非标准的加载-存储语义 - 即它不能依赖 CPU 寄存器中的副本与内存中的值保持一致。
一般的副作用是禁用围绕该变量的任何优化(即那些依赖于内存中的存储而不改变其下方的优化)。结果是每次使用时都会从内存中重新加载。

这是volatile 在多线程情况下使用的少数场合之一。

【讨论】:

  • volatile 表示变量的读取和写入是可观察的行为,仅此而已(保存特定于编译器的扩展)。它不提供内存屏障,也不阻止 CPU 重新排序。如果是这样,C++11 就不会添加std::atomic<>
【解决方案3】:

这取决于您为当前值表使用的内容。如果您使用的是像 SQLServer 这样的数据库,那么您不必担心,因为数据库会处理它。

如果您使用的是文件系统,那么问题仍然存在。

您可以编写一个基于 TCP 的客户端/服务器,将请求排队并按顺序响应它们。

如果您使用的是内存,那么您需要使用互斥体。

【讨论】:

  • 从 CVT 是(并且需要)在内存中的问题很清楚
  • 问题似乎已被编辑,在原始问题中(至少对我而言)并不明显。
【解决方案4】:

只要您的 32 位 int 在内存中正确对齐,我猜这是因为它在大多数现代平台上默认设置,读取 int 实际上是线程安全的。

【讨论】:

  • 有一些(几乎完全是理论上的,并且很可能是人为的)边缘情况,编译器可以在读取当前值时进行 CSE 优化。如果您担心在 SMP 系统上对表的写入相对于彼此完成的顺序,它会变得更有成效。
  • int 对齐并不意味着它是线程安全的(具有必要的内存屏障并且没有数据争用)。
  • @GManNickG 你的意思是“竞争条件”而不是“数据竞争”吗?
  • @GManNickG 尝试再次阅读问题。 OP 说:“我不在乎阅读器线程是否没有获得存储的绝对最新值,我只是担心在更改该位置时尝试读取该位置。”他所需要的只是一些有效值。它可能刚刚被更新,或者正在被另一个线程更新,OP 不在乎近似 值对他来说就可以了。他担心一个线程试图读取int 值而该值的字节仅部分更新的情况,这在实践中不应该发生在对齐的数据中。
  • @DesmondHume:这很好,但它只解决了一半的问题,另一半正在重新排序。
猜你喜欢
  • 2011-12-01
  • 1970-01-01
  • 2015-08-25
  • 1970-01-01
  • 1970-01-01
  • 2012-10-27
  • 1970-01-01
  • 1970-01-01
  • 2016-07-11
相关资源
最近更新 更多