volatile
关键字是否可以跨线程强制实施可见性?例如:
volatile int bar;
mutex mut;
void foo()
{
bar = 4;
// (*) Possible other thread changes to `bar`. No instructions here,
// just time that passes.
lock(&mut);
// (1) If 'bar' had _not_ been declared 'volatile', would the compiler
// be allowed to assume 'bar' is '4' here?
//
// (2) If 'bar' _is_ declared 'volatile', the compiler is
// forced to add the necessary instructions such that changes to
// 'bar' that may have occurred during (*) are visible here.
unlock(&mut)
}
不询问原子性或排序(我假设任何合理的lock(mutex)
实现添加适当的内存和编译器围栏,适用于架构) - 只是一个可见性问题。
答案 0 :(得分:1)
即使您没有将bar
标记为volatile,编译器也无法确定该值是否同时未被修改,因为它是全局值。
所以它必须再次读取它(调用互斥函数,它可以是访问bar
并更改它的任何函数),是否可以是volatile。
对于local
值,绑定,例如,在硬件寄存器上的绑定可能会有所不同,而且可能与程序执行无关,而volatile
关键字是必需的。
答案 1 :(得分:1)
(1)如果'bar'将 声明为'volatile',编译器是否会 可以假设'bar'在这里是'4'吗?
volatile
的属性很容易理解:每次都从内存位置读取它而不优化任何相关的内容。无论是否存在多个线程,volatile变量仍然保持相同的属性。
这是否意味着volatile
跨线程强制执行“可见性”?
它可能会作为其财产的副作用。但在多线程程序中这不是必需的。使用适当的同步原语(例如互斥锁或原子变量),编译器必须跨不同的线程强制执行对象中的可见性或最后存储的值。这是C11和POSIX线程中的情况。支持多线程程序的编译器应该能够生成代码正确的代码,强制执行此操作而不需要volatile
。所以,答案是否定的;在多线程程序中不需要volatile
来强制更改对象(变量)。