1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > volatile(防止编译器对代码进行优化 常用于多线程环境中)

volatile(防止编译器对代码进行优化 常用于多线程环境中)

时间:2019-11-20 22:24:24

相关推荐

volatile(防止编译器对代码进行优化 常用于多线程环境中)

一.单词解释

adj.易变的;无定性的;无常性的;可能急剧波动的

二.使用说明:

volatile表示这变量可能会被意想不到地改变,提示编译器别优化老子,编译器就不会去假设这个变量的值了。

建议你用volatile修饰在多个线程中使用的原生类型变量

举例说明:

class Gadget{public:void Wait(){while (!flag_){Sleep(1000); // sleeps for 1000 milliseconds}}

void Wakeup(){flag_ = true;}...private:bool flag_;};

上面代码中的Wait()想要实现每隔一秒对flag_进行判断,如果flag_被另外的线程改为true的话,就会跳出循环.

但实际上这样设计是存在问题的,原因就在于while循环中,编译器认为flag_的值不会改变,那么它会把flag_的值从内存中缓存到寄存器中,这样的话就提高了访问效率.这对于单线程是很好的优化,但是这样会让程序变得不正确.当另一个线程改变了内存中flag_的值时,while循环还是访问寄存器中的值,这样就导致了出现问题.

C和C++给你提供了显式禁用这种缓存优化的机会。如果你声明变量是使用了volatile修饰符,编译器就不会把这个变量缓存在寄存器里——每次访问都将去存取变量在内存中的实际位置。这样你要对Gadget的Wait/Wakeup做的修改就是给flag_加上正确的修饰:

class Gadget{public:... as above ...private:volatile bool flag_;};

参考文章:/xuwentao37x/article/details/27804169

三代码示例

#include <iostream>#include <windows.h>using namespace std;class Test{private:volatile bool m_bFlag; //在VS下不加volatile也可以正确执行,不过为了安全还是需要加上的.public:Test(){m_bFlag = false;}void Wait(){while (!m_bFlag){cout << "I'm Sleeping" << endl;Sleep(1000);}cout << "I'm awake" << endl;}void WakeUp(){m_bFlag = true;}};DWORD WINAPI ThreadFun2(void *param){Test *tThread = (Test *)param;tThread->WakeUp();return 0;}DWORD WINAPI ThreadFun1(void *param){Test *tThread = (Test *)param;tThread->Wait();return 0;}//用两个子线程实现,发现两个子线程之间的生存期是相互独立的.它们只受主线程的影响.int main(){Test t;HANDLE h[2];h[0] = CreateThread(NULL, 0, ThreadFun1, &t, 0, NULL);Sleep(10);//如果不加这个Sleep,多数情况下会先打印Sleeping,然后打印awake,但是也有情况会直接打印awake.h[1] = CreateThread(NULL, 0, ThreadFun2, &t, 0, NULL);WaitForMultipleObjects(2, h, TRUE, INFINITE);return 0;}

关于这个例子,多线程相关的探讨可以参见自己总结的这篇文章:https://i-/posts/edit-done;postId=12708937

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。