c++ - C++ IntAtomicGet、GotW 的原因

标签 c++ multithreading atomic gotw

GotW article #45 ,赫伯陈述如下:

void String::AboutToModify(
  size_t n,
  bool   bMarkUnshareable /* = false */
) {
  if( data_->refs > 1 && data_->refs != Unshareable ) {
    /* ... etc. ... */

This if-condition is not thread-safe. For one thing, evaluating even "data_->refs > 1" may not be atomic; if so, it's possible that if thread 1 tries to evaluate "data_->refs > 1" while thread 2 is updating the value of refs, the value read from data_->refs might be anything -- 1, 2, or even something that's neither the original value nor the new value.

此外,他指出 data_->refs 在与 1 比较和与 Unshareable 比较之间可能会被修改。

进一步,我们找到了解决方案:

void String::AboutToModify(
  size_t n,
  bool   bMarkUnshareable /* = false */
) {
  int refs = IntAtomicGet( data_->refs );
  if( refs > 1 && refs != Unshareable ) {
    /* ... etc. ...*/

现在,我明白两次比较使用相同的引用,解决问题 2。但是为什么使用 IntAtomicGet?我在该主题的搜索中没有找到任何内容 - 所有原子操作都集中在读取、修改、写入操作,而这里我们只是进行读取。那么我们可以做...

int refs = data_->refs;

...最终可能只是一条指令?

最佳答案

不同的平台对读/写操作的原子性做出不同的 promise 。例如,x86 保证读取双字(4 字节)将是一个原子操作。但是,您不能假设这对于任何架构都是如此,而且很可能不会。

如果您计划将代码移植到不同的平台,这样的假设可能会给您带来麻烦,并导致代码中出现奇怪的竞争条件。因此,最好保护自己并明确使读/写操作原子化。

关于c++ - C++ IntAtomicGet、GotW 的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33246133/

相关文章:

c++ - boost::thread 的 shared_ptr 断言失败

linux - Linux 和 Windows 中的多线程模型

c# - 使用后台线程时高效显示文件状态

multithreading - 给定足够的内存,当只有一个专用的写线程时,是否不需要锁?

c++ - 从 'int' 到 'const char*' 问题 C++ 的无效转换

c++ - MATLAB BWLABEL 的 OpenCV 替代品

java - 为什么java.util.concurrent.atomic.AtomicBoolean内部是用int实现的?

multithreading - SFENCE 是否会阻止存储缓冲区对 MESI 隐藏更改?

c++ - 声明一个大小为 std::streamoff 的数组

C# AppDomains 和线程