- 论坛徽章:
- 0
|
本帖最后由 狗蛋 于 2011-10-18 14:42 编辑
这个其实就是鸭子哲学:一个动物,如果它看起来像鸭子,叫起来也像鸭子,那么就不妨先把它当鸭子。
C语言不管你后台如何实现,但最终结果,必须和按顺序执行每一条语句所达到的结果一致:也就是说,不管你后面如何捣蛋,结果像顺序执行的就行了。
这种哲学给了编译器/CPU广阔的优化余地,正如之前网友讨论的:
int i=0;
i=1;
可能会直接被编译器删除把i赋值为0的操作;
我之前也多次提到过常量优化,如:
int i=42;
int j=max(i, 99); //1
.... //其它乱七八糟一大陀子,用到了i但没用到j
.... //2 使用j的值
其中,//1处的max(i, 99)的声明如果是max(const int, const int),那么这个max函数调用可能就不会执行,直到//2位置才会真正执行(当然,如果前面就return回去了,那么就永远不执行它)。
同理,如果//1后面没有修改i,那么引用到i的地方也全都可以直接用立即数42代替,直到i被修改或有可能被修改的那一行为止。
换言之,c语言不阻止编译器从整体上揣摩代码功能,并据此调整代码执行次序甚至删除无效代码,只要最终结果和“代码按顺序执行”时一致即可。
不过,在多线程情况下,这种优化可能造成问题。
因为在线程A中不会修改的变量,可能在线程B中被频繁改变。这样,仅仅分析一个局部的代码块是不足以做出正确优化的。
遇到这种情况,可以用volatile修饰被影响的数据,告诉编译器这个数据会被其它代码修改/读取,就可以阻止这种“常量优化”。
这样才能保证多线程环境下优化过的程序执行结果,和按行顺序执行的结果一致。
形象点说,本来一个动物看起来像鸭子、叫起来像鸭子已经足够了;但由于多线程概念的出现,我们又需要它下鸭蛋了——volatile就是通知编译器这个的:喂,老兄,上面这次连鸭蛋也要检查,你别露馅了! |
|