c++ - 我应该为在不同线程之间共享内存的每个对象指定 volatile 关键字吗

标签 c++ multithreading volatile

我刚刚读了Do not use volatile as a synchronization primitive CERT 网站上的文章,注意到编译器理论上可以优化以下代码,将 flag 变量存储在寄存器中,而不是修改不同线程之间共享的实际内存:

bool flag = false;//Not declaring as {{volatile}} is wrong. But even by declaring {{volatile}} this code is still erroneous
void test() {
  while (!flag) {
    Sleep(1000); // sleeps for 1000 milliseconds
  }
}
void Wakeup() {
  flag = true;
}
void debit(int amount){
   test();
   account_balance -= amount;//We think it is safe to go inside the critical section
}

我说得对吗?

我是否真的需要为程序中的每个对象使用 volatile 关键字以在不同线程之间共享其内存?不是因为它为我做了某种同步(无论如何我需要使用互斥体或任何其他同步原语来完成这样的任务)而是因为编译器可能优化我的代码并将所有共享变量存储在寄存器中所以其他线程将永远不会获得更新的值?

最佳答案

不仅仅是将它们存储在寄存器中,在共享主内存和 CPU 之间还有各种级别的缓存。大部分缓存是针对每个 CPU 内核的,因此其他内核在很长一段时间内不会看到任何更改(或者如果其他内核正在修改同一内存,那么这些更改可能会完全丢失)。

无法保证缓存的行为方式,即使某些事情对当前处理器来说是正确的,但对旧处理器或下一代处理器来说可能并不正确。为了编写安全的多线程代码,您需要正确地执行它。为此,最简单的方法是使用提供的库和工具。尝试使用像 volatile 这样的低级原语自己来做是一件非常困难的事情,涉及大量深入的知识。

关于c++ - 我应该为在不同线程之间共享内存的每个对象指定 volatile 关键字吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33651461/

相关文章:

c++ - 将 `std::default_delete` 专门化为 `std::shared_ptr`

c++ - 正确使用枚举元素

c++ - 变体,C++中的存在多态性

java - 在Java中将线程更改为进程

c++ - 互斥体的存在是否有助于摆脱 volatile 关键字?

C++如何在获取其索引位置后获取子字符串

c - 使用互斥体和信号量

java - 线程之间是否共享静态变量?

java - java 中的 volatile 与 threadLocal

c++ - 为什么volatile静态成员初始化会产生重定义编译错误?