2015-05-04 20 views
1

为什么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); 

回答

5

首先,你的假设是错误的,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。它不会伤害太多,但可能有助于在一些角落案件。

-2

语义原子操作意味着有多个并发线程访问变量值。这就是volatile说明符的用途。

您提供的两个参考文献都非常有问题,并且通常不适用(通常在SW工程中)。如果您有数据,可以在软件中同时访问/修改数据,则必须是volatile

有用例,其中volatile是绝对必要的:内核驱动程序。您不能让编译器优化对映射到设备的内存区域的访问。

有很多基于volatile的编程范例。例如,只有在快速锁定失败时,正常关键部分/互斥锁才使用volatile变量快速锁定并回退到信号/事件/等。

+0

跨线程的共享变量不*具有* volatile *。 volatile的使用通常与多线程无关。 'volatile'意味着对象的值可以在没有对实现的控制的情况下进行更改,因此,编译器不会在序列点之间执行访问优化(虽然它们允许在序列点之间)。这就是为什么它对驱动程序编程有用,但它与多线程的关系不存在。线程间的共享变量需要与互斥锁或类似的锁定基元同步。 –

+0

@FilipeGonçalves跨变量同步不会消除优化。示例是循环:如果您有一个循环退出变量,并且它不是易失性的,则编译器可以完全优化对其的访问。 –