C++11的多线程相关
- volatile: 在c++中,这个关键字主要是表示当前值每次读取的时候都需要从内存中读取,不能使用寄存器缓存的值。有的人很容易把他的作用和atomic或者使用mutex实现的原子操作弄混,实质上他们的意义是完全不同的。volatile除了用在io映射内存之类地方之外,它主要的一个作用就是用在如下类似的代码上面
volatile bool ready = false; //如果不加static就整个源程序都可以访问,不过其他地方要用extern声明一下
void initiazer(int &&ref)
{
std::cout << "Inside thread: " << std::this_thread::get_id() << " ref: " << ref << std::endl;
//std::this_thread::sleep_for(std::chrono::milliseconds(1));
ready = true;
}
int main()
{
std::thread th(initiazer, int(6));
int counter = 0;
while (!ready)
{
counter++;
std::cout << "\nready is false" << std::endl;
//break;
}
std::cout << "\nready is true " << counter << std::endl;
th.join();
getchar();
return 0;
}我在vs2015中测试了一下,当不加volatile修饰ready变量时,主线程是有可能因为编译器优化而陷入死循环,即每次都从寄存器读取ready,发现都是false。当我在循环中加上“std::cout << "\nready is false" << std::endl;”这行代码的时候, 主线程可以正常读到ready被另一个线程修改的值。这个是由于编译器的优化规则导致的。 如果一个全局变量的2次读之间 1.没有调用任何非inline函数。 2.没有任何内嵌汇编语句。 那么编译器在第二次访问这个变量的时候,会直接使用第一次访问的值。
而为什么使用了std::out就可以了,这是因为进行了函数调用,编译器认为在进行函数调用之后所有非局部变量都需要重新从内存中取值,被取过地址或者引用的局部变量往往也需要重新被求值。
此外还有一点要注意,volatile关键字的这种内存屏障作用在多核机器上可能是不管用的
- atomic
参考文献
未完待续