volatile
2015-07-09 15:31
295 查看
只是个小小的关键字
尽管C和C++标准都明显地对线程保持沉默,它们还是对多线程做了小小的让步,这种让步表现为volatile关键字。
正如它的更为人所知的伙伴const, volatile是个类型修正符(type modifier)。。它的作用是和变量连用使变量能被不同线程访问和修改。根本上说,如果没有volatile的话,要么不可能写出多线程程序,要么编译器浪费极大的优化机会。现在来解释为什么会是这种情况。
考虑下面代码:
class Gadget
{
public:
void Wait ()
{
while (!flag_)
{
Sleep(1000); //睡眠1000毫秒
}
}
void Wakeup ()
{
flag_ = true;
}
...
private:
bool flag_;
};
上面Gadget::Wait的作用是每秒检查一次flag_成员变量,如果那个变量被其他线程设为true时返回。至少这是程序员的本来意图,但,唉,Wait函数是错误的。
如果编译器断定Sleep(1000)是对外部库的一个调用,而且这个调用不可能修改成员变量flag_。那么编译器会决定在寄存器中缓存flag_并且用那个寄存器替代较慢的内存。这对单线程代码来说是非常好的优化,但在现在这个情况下,这个优化破坏了正确性:你对某个Gadget对象调用Wait后,尽管另一个线程调用了Wakeup,Wait还会永远循环下去。这是因为对flag_的修改不会反映到缓存flag_的寄存器。这个优化实在是......过度优化了。
把变量缓存到寄存器中在大多数时候是一项非常有用的优化,浪费掉就太可惜了。C和C++给你机会来显式禁用这个优化。如果你用volatile标识一个变量,编译器就不会把那个变量缓存到积存器中——对变量的每次访问都直接通过实际内存的位置。所以要让Gadget的Wait/Wakeup正常工作只要正确修饰flag_
class Gadget
{
public:
...同上...
private:
volatile bool flag_;
};
大多数对volatile用途和用法的解释到此为止,并且建议你在多线程中对基本类型加volatile标识符。但是,用volatile你可以做更多事情,因为它是C++奇妙的类型系统的一部分。
尽管C和C++标准都明显地对线程保持沉默,它们还是对多线程做了小小的让步,这种让步表现为volatile关键字。
正如它的更为人所知的伙伴const, volatile是个类型修正符(type modifier)。。它的作用是和变量连用使变量能被不同线程访问和修改。根本上说,如果没有volatile的话,要么不可能写出多线程程序,要么编译器浪费极大的优化机会。现在来解释为什么会是这种情况。
考虑下面代码:
class Gadget
{
public:
void Wait ()
{
while (!flag_)
{
Sleep(1000); //睡眠1000毫秒
}
}
void Wakeup ()
{
flag_ = true;
}
...
private:
bool flag_;
};
上面Gadget::Wait的作用是每秒检查一次flag_成员变量,如果那个变量被其他线程设为true时返回。至少这是程序员的本来意图,但,唉,Wait函数是错误的。
如果编译器断定Sleep(1000)是对外部库的一个调用,而且这个调用不可能修改成员变量flag_。那么编译器会决定在寄存器中缓存flag_并且用那个寄存器替代较慢的内存。这对单线程代码来说是非常好的优化,但在现在这个情况下,这个优化破坏了正确性:你对某个Gadget对象调用Wait后,尽管另一个线程调用了Wakeup,Wait还会永远循环下去。这是因为对flag_的修改不会反映到缓存flag_的寄存器。这个优化实在是......过度优化了。
把变量缓存到寄存器中在大多数时候是一项非常有用的优化,浪费掉就太可惜了。C和C++给你机会来显式禁用这个优化。如果你用volatile标识一个变量,编译器就不会把那个变量缓存到积存器中——对变量的每次访问都直接通过实际内存的位置。所以要让Gadget的Wait/Wakeup正常工作只要正确修饰flag_
class Gadget
{
public:
...同上...
private:
volatile bool flag_;
};
大多数对volatile用途和用法的解释到此为止,并且建议你在多线程中对基本类型加volatile标识符。但是,用volatile你可以做更多事情,因为它是C++奇妙的类型系统的一部分。
相关文章推荐
- 前端学习——零
- (一)androidpn-server tomcat版源码解析之--项目启动
- Linux 内核编译选项详解
- C++关键字大总结
- 学堂在线c++进阶编程题 11-2
- poj 2185 Milking Grid(KMP)
- KSS2-成本中心作业价格分割(错误!!!)
- 用结构体struct(数组)实现桶排序
- 凸优化:ADMM(Alternating Direction Method of Multipliers)交替方向乘子算法系列之四: General Patterns
- Android手机定位技术的发展
- input checkbox 复选框 全选 操作 attr checked 第二次 不起作用
- ESB (Enterprise Service Bus) 入门
- for、while循环及其变体
- LINUX GDB调试实例
- Active Directory:Dsquery Commands
- JavaScript中的闭包(Closure)
- 创建字符串
- Android View 仿iOS SwitchButton
- 网络监听函数listen()
- CodeForces 228D. Zigzag(线段树暴力)