这里 http://hedengcheng.com/?p=725 有对volatile 非常详细的解释,看完之后,心里一惊,因为我刚好在一个项目里用了文中错误示范那种方式来做线程同步,场景如下:
Thread1 对性能要求非常高,它有一些中间数据需要定时同步给数据库,我就增加了一个线程Thread2 来帮它做(Thread2还干了很多其他事情),基本做法是:thread1 干完do_something后,给一个全局的 volatile flag 置1;Thread2在一个大循环里,当检测到flag值是1,则会去读thread1产生的中间数据并入库。
按照帖子的说法,flag=true 对应的汇编指令可能被编译器插入到 do_something 对应的指令中间,无法保证do_something做完值才变成1. 根据查找,发现gcc下有一个指令可以强制编译器和CPU 按顺序执行:
#define BARRIER() do{ asm volatile("" ::: "memory");}while(0)
这样代码变成
Thread1() Thread2()
{ {
do_something... if(flag==true)
BARRIER; {
flag = true; BARRIER;
} other thing...
}
}