volatile
遇到一个问题:
一个线程赋值给一个指针内容后,在定时器线程里,这个指针是空的,问题原因还在查找中。
对这个指针时效性要求并不高,只要在1秒内生效即可。但因为检查时,要的内容
微软的定义文档是:
可以使用 限定符提供对异步进程(如中断处理程序)使用的内存 volatile 位置的访问。 当 volatile 用于也具有 __restrict 关键字的volatile变量时, volatile 优先。 如果 struct 成员标记为 volatile ,则 volatile 传播到整个 结构。 如果结构的长度不能通过使用一个指令在当前体系结构上复制,则 可能会 volatile 完全丢失该结构。 如果 volatile 满足以下条件之一,关键字对字段可能不起作用: 可变字段的长度超过可使用一条指令在当前体系结构上复制的最大大小。 最外层包含的长度(如果它是可能嵌套的成员)超过了可以使用一条指令在当前体系结构上 structstruct 复制的最大大小。 尽管处理器不重新排列不可缓存的内存访问,但不可缓存的变量必须标记为 ,以确保编译器不会重新排列 volatile 内存访问。 声明为 的对象 volatile 不会在某些优化中使用,因为它们的值可能随时更改。 系统始终在请求可变对象的当前值时读取该值,即使前面的指令要求来自同一个对象的值。 此外,对象的值在赋值时立即写入
机器翻译的实在差劲,下面时英文解释:
You can use the volatile
qualifier to provide access to memory locations that are used by asynchronous processes such as interrupt handlers.
When volatile
is used on a variable that also has the __restrict keyword, volatile
takes precedence.
If a struct
member is marked as volatile
, then volatile
is propagated to the whole structure. If a structure does not have a length that can be copied on the current architecture by using one instruction, volatile
may be completely lost on that structure.
The volatile
keyword may have no effect on a field if one of the following conditions is true:
-
The length of the volatile field exceeds the maximum size that can be copied on the current architecture by using one instruction.
-
The length of the outermost containing
struct
—or if it's a member of a possibly nestedstruct
—exceeds the maximum size that can be copied on the current architecture by using one instruction.
Although the processor does not reorder un-cacheable memory accesses, un-cacheable variables must be marked as volatile
to guarantee that the compiler does not reorder the memory accesses.
Objects that are declared as volatile
are not used in certain optimizations because their values can change at any time. The system always reads the current value of a volatile object when it is requested, even if a previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment.
我的理解:
当一个结构体(类)中,含有一个volatile 字段时,整个结构(类)都是volatile 属性的。
结构体如果很大,系统不好复制时,即使不用加这个属性,他也会自动去原始位置找该值。
被标记的变量,一般不被优化。
写了一个简单的测试程序,但没有测试出volatile 的作用。
#include <iostream> #include <thread> #include <string.h> #include <vector> using namespace std; struct A { int a = -1; int b = -10; char ch[100]; }; A* x = nullptr; volatile char* p = nullptr; char* p2 = nullptr; volatile bool g_end = false; int main() { char pool[100][10] = {{0}}; vector<A*> As; As.resize(100); thread t2([&]{ while (! g_end) { std::this_thread::sleep_for(1ms); if (p && p2) { printf(" 2-->%s %s",p, p2); } if (x) { printf(" 2-->%d",x->a); } } }); thread t1([&]{ for(int i=0; i< 100; ++i) { sprintf_s(pool[i],"%09d",i); p = pool[i]; p2 = pool[i]; As[i] = new A; As[i]->a = i; x = As[i]; printf("\n1--> %s %s %d\n",p, p2, x->a); std::this_thread::sleep_for(10ms); } g_end =true; }); t1.join(); t2.join(); return 0; }
这段代码,无论加不加volatile , 效果都一样。 有点无从下手。