可能重复:
C++:什么时候有挥发性关键字帮你?
我从来没有用过它,但我想知道为什么人们会用它?它到底是做什么的?我搜索了论坛,发现它只是C#或Java主题.
考虑以下spin_lock()实现,最初来自这个答案:
void spin_lock(volatile bool* lock)  {  
    for (;;) {
        // inserts an acquire memory barrier and a compiler barrier
        if (!__atomic_test_and_set(lock, __ATOMIC_ACQUIRE))
            return;
        while (*lock)  // no barriers; is it OK?
            cpu_relax();
    }
}
我所知道的:
volatile防止编译器*lock在while循环的每次迭代中优化重新读取;volatile 不插入内存或编译器障碍 ;x86(例如在Linux内核中)和其他一些架构;spin_lock()执行针对通用体系结构; 这个例子插入它们__atomic_test_and_set().问题:
volatile这里是否足够或者是否存在while循环中需要内存或编译器障碍或原子操作的架构或编译器?
1.1根据C++标准?
1.2在实践中,对于已知的体系结构和编译器,特别是它支持的GCC和平台?
while根据C++11它的内存模型,循环是否安全?有几个相关的问题,但我无法从它们构建一个明确和明确的答案:
原则上:是的,如果程序执行从一个核心移动到下一个核心,则可能看不到在先前核心上发生的所有写入. …
考虑以下对volatile内存的写入顺序,我从David Chisnall在InformIT的文章 "理解C11和C++ 11 Atomics"中获取:
volatile int a = 1;
volatile int b = 2;
             a = 3;
我对C++ 98的理解是,根据C++ 98 1.9,这些操作无法重新排序:
符合实现需要模拟(仅)抽象机器的可观察行为,如下所述...抽象机器的可观察行为是它对易失性数据的读写顺序和对库I/O函数的调用
Chisnall说,对订单保存的约束仅适用于单个变量,写出符合要求的实现可以生成执行此操作的代码:
a = 1;
a = 3;
b = 2;
或这个:
b = 2;
a = 1;
a = 3;
C++ 11重复了C++ 98的措辞
符合实现需要模拟(仅)抽象机器的可观察行为,如下所述.
但这说关于volatiles(1.9/8):
严格根据抽象机器的规则来评估对volatile对象的访问.
1.9/12表示访问volatileglvalue(包括变量a,b及c以上)是副作用,1.9/14表示一个完整表达式(例如,一个语句)中的副作用必须先于后面的副作用在同一个线程中完整表达.这使我得出结论,Chisnall显示的两个重新排序是无效的,因为它们不符合抽象机器所规定的排序.  
我忽略了什么,还是Chisnall错了?
(请注意,这不是一个线程问题.问题是是否允许编译器重新排序对volatile单个线程中不同变量的访问.)
C标准规定,当变量的值可能会在程序正常执行流程之外更改时,应在变量的定义中使用volatile关键字。
如果在正常执行流程中更改(写入)了全局变量,并且仅在该正常流程之外(在中断中)读取。这个变量需要可变吗?又为什么呢?
考虑到创建/加入线程时隐含的同步,该代码工作所需的最小框架是什么??没有?xstd::atomicvolatile
#include <thread>
#include <cassert>
int main() {
    int x = 123; // ***
    std::thread( [ & ] { assert( x == 123 ); x = 321; } ).join();
    assert( x == 321 );
    return 0;
}
我非常了解volatileC++中的关键字.但在C#中,它似乎采用了不同的含义,与多线程更相关.我认为bool操作是原子的,我认为如果操作是原子的,你就不会有线程问题.我错过了什么?
我们知道它可以用Java和JavaScript.
但问题是,可以在下面的条件永远评估为true 在C或C++?
if(a==1 && a==2 && a==3) 
    printf("SUCCESS");
编辑
如果a是整数.
根据 cppreference,一个volatile限定变量的存储不能重新排序为另一个volatile限定变量。换句话说,在下面的示例中,当 y 变为 20 时,可以保证 x 为 10。
volatile int x, y;
...
x = 10;
y = 20;
根据维基百科,ARM 处理器的一个存储可以在另一个存储之后重新排序。因此,在下面的示例中,第二个存储可以在第一个存储之前执行,因为两个目的地是不相交的,因此它们可以自由地重新排序。
str     r1, [r3]
str     r2, [r3, #4]
有了这样的理解,我写了一个玩具程序:
volatile int x, y;
int main() {
    x = 10;
    y = 20;
}
我预计生成的程序集中会出现一些围栏,以保证 x 和 y 的存储顺序。但为 ARM生成的程序集是:
main:
        movw    r3, #:lower16:.LANCHOR0
        movt    r3, #:upper16:.LANCHOR0
        movs    r1, #10
        movs    r2, #20
        movs    r0, #0
        str     r1, [r3]
        str     r2, [r3, #4] …