关于挥发性使用的规则是严格的吗?

Poo*_*ria 4 c++ multithreading rules volatile

我看过这句话:

一般规则是,如果你有必须在多个线程之间共享的基本类型的变量,则声明那些变量 volatile

这篇文章,这句话:

通常,任何可以异步发音的数据都应声明为volatile.

这个页面,现在考虑这个引入的规则我想知道你能带一个案例的例子,尽管存在对数据的异步访问,声明数据volatile在实践中没用,或者没有这样的例外情况和规则是严格的.

sbi*_*sbi 12

我记得那篇文章发表的时候,我记得在comp.lang.c ++上进行的无休止的讨论.

IIRC,Andrei劫持了volatile关键字,用它来区分不同的函数重载.(请参阅Scott Meyers的这篇文章,了解另一个这样的想法.)他所做的很棒,因为它允许编译器抓住你,如果你搞乱对象的受保护和不受保护的访问(非常像编译器捕获你应该尝试修改常量).但除了它对您有所帮助之外,它与实际保护对象的并发访问无关.

问题只是90%的人只看了一眼文章,他们看到的只是volatile同一文章中的"线索".根据他们的知识,他们要么得出错误的结论,这volatile对线程有好处(你似乎已经这样做了),或者他们因为引导别人得出错误的结论而对他大喊大叫.
很少有人能够真正完整地阅读这篇文章,并了解他的真实所在.

  • 如果可以,我会+15 (3认同)
  • @Pooria:我们不是来和你一起战斗的.我们是来帮助你的.如果sbi和我正在回答您没有问的问题,那么*请重申问题* (3认同)

Mik*_*ron 11

我不能代表实际的异步访问场景,因为我不太擅长多线程,但volatile修饰符的作用是告诉编译器:

"听着,这可能会在任何时候发生变化,所以不要将其缓存或放入寄存器或做任何类似的疯狂,好吗?"

它不能防止异步写入,它只是禁用在外部力量可以更改变量时无效的优化.

编辑:作为一个潜在的例子,一个不涉及多线程的例子(但是,确实涉及异常复杂的代码;),这里有一个volatile很重要的情况:

volatile bool keepRunning = true;
void Stuff() {
    int notAPointer = 0;

    notAPointer = (int)(&keepRunning); //Don't do this! Especially on 64-bit processors!

    while(keepRunning) {
        *(bool*)(notAPointer) = false;
    }

    printf("The loop terminated!");
}
Run Code Online (Sandbox Code Playgroud)

如果没有那个volatile修饰符,编译器可能会"嘿,keepRunning永远不会被修改,所以我甚至不需要生成检查它的代码!",实际上我们只是秘密修改它.

(实际上,这可能仍然适用于非优化构建.而且,如果编译器是智能的并且注意到指针被采用它也可能仍然有用.但是,原理是相同的)