为什么C11 atomic_load
/atomic_store
函数中的参数具有volatile
限定符?由于已确定volatile
对于并发用例是无用的(例如,1,2)。所有的C11 atomic_load/store和volatile限定符
atomic_load(const volatile A* obj);
void atomic_store(volatile A* obj , C desired);
为什么C11 atomic_load
/atomic_store
函数中的参数具有volatile
限定符?由于已确定volatile
对于并发用例是无用的(例如,1,2)。所有的C11 atomic_load/store和volatile限定符
atomic_load(const volatile A* obj);
void atomic_store(volatile A* obj , C desired);
首先,你的假设是错误的,volatile
也不是一无是处,它是不足够的,这是一个不同的事情。
您引用的接口必须具有volatile
限定,否则它们不适用于具有此限定条件的对象。
现在volatile
是C11的一个难题,因为目前存在争议,如果它仅在对象本身是volatile
限定的或只有当前访问的类型有效。但是可以肯定的是,这里的_Atomic
对象的规则与其他对象没有多大区别。因此,如果您有一个非修改的非volatile
访问权限,编译器可以优化访问权限并依赖以前已知的值。
只有这样的操作,您可以使用一个_Atomic
办正在评估它:
_Atomic size_t counter = ATOMIC_VAR_INIT(0);
++counter; // safe: sequential consistency
...
printf("counter: %zu\n", counter); // may use some previous value
...
printf("counter: %zu\n", atomic_load(&counter)); // should use actual value
现在的“应该”在这里是因为关于我上面提到volatile
不同的解释。如果您想确保没有发生负载优化,则应始终声明_Atomic
对象volatile
。它不会伤害太多,但可能有助于在一些角落案件。
语义原子操作意味着有多个并发线程访问变量值。这就是volatile
说明符的用途。
您提供的两个参考文献都非常有问题,并且通常不适用(通常在SW工程中)。如果您有数据,可以在软件中同时访问/修改数据,则必须是volatile
。
有用例,其中volatile
是绝对必要的:内核驱动程序。您不能让编译器优化对映射到设备的内存区域的访问。
有很多基于volatile
的编程范例。例如,只有在快速锁定失败时,正常关键部分/互斥锁才使用volatile
变量快速锁定并回退到信号/事件/等。
跨线程的共享变量不*具有* volatile *。 volatile的使用通常与多线程无关。 'volatile'意味着对象的值可以在没有对实现的控制的情况下进行更改,因此,编译器不会在序列点之间执行访问优化(虽然它们允许在序列点之间)。这就是为什么它对驱动程序编程有用,但它与多线程的关系不存在。线程间的共享变量需要与互斥锁或类似的锁定基元同步。 –
@FilipeGonçalves跨变量同步不会消除优化。示例是循环:如果您有一个循环退出变量,并且它不是易失性的,则编译器可以完全优化对其的访问。 –