什么时候使用multithreadingvolatile?

如果有两个线程访问一个全局variables,那么很多教程都会说variables是volatile的,以防止编译器将这个variablescaching在一个寄存器中,从而不能正确更新。 然而,两个线程都访问一个共享variables是通过互斥体来保护的东西,不是吗? 但是在这种情况下,在线程locking和释放互斥体之间,代码是在一个只有一个线程可以访问variables的关键部分,在这种情况下,variables不需要是易失性的?

那么在multithreading程序中volatile的用途和用途是什么呢?

简短和快速的回​​答 :对于平台不可知的multithreading应用程序编程来说, volatile (几乎)是无用的。 它不提供任何同步,它不会创build内存隔离,也不会确保执行操作的顺序。 它不会使操作成为primefaces。 它不会让你的代码神奇地线程安全。 volatile可能是所有C ++中最容易被误解的工具。 看到这个 , 这个和这个有关volatile更多信息

另一方面, volatile有一些用处,可能不是那么明显。 它的使用方式与使用const方式非常相似,可以帮助编译器向您显示在何处以非保护方式访问共享资源的错误。 Alexandrescu在本文中讨论了这种用法。 但是,这基本上是以一种经常被看作是一种devise的方式来使用C ++types的系统,并且可以唤起未定义的行为。

当与存储器映射硬件,信号处理器和setjmp机器代码指令接口时, volatile被专门用于使用。 这使volatile直接适用于系统级编程,而不是正常的应用程序级编程。

2003 C ++标准并没有说volatile对variables应用了任何types的Acquire或Release语义。 事实上,标准在multithreading的所有问题上是完全沉默的。 但是,特定的平台在volatilevariables上应用了Acquire和Release语义。

[更新C ++ 11]

现在C ++ 11标准确实直接在内存模型和语言承认multithreading,它提供了一些库平台无关的处理方式。 但是volatile的语义仍然没有改变。 volatile仍然不是一个同步机制。 Bjarne Stroustrup在TCPPPL4E中表示:

除了直接处理硬件的底层代码之外,不要使用volatile

不要认为volatile在内存模型中有特殊的含义。 它不是。 它不像一些后来的语言那样是同步机制。 要获得同步,请使用atomicmutexcondition_variable

[/结束更新]

以上所有都适用于2003标准(现在是2011标准)定义的C ++语言本身。 然而,一些特定的平台会增加额外的function或者限制什么是volatile 。 例如,在MSVC 2010中(至less)Acquire和Release语义确实适用于对volatilevariables的某些操作。 从MSDN :

在进行优化时,编译器必须在对易失性对象的引用以及对其他全局对象的引用之间保持sorting。 尤其是,

对易失性对象(易失性写入)的写入具有释放语义; 在写入指令序列中的易失性对象之前发生的对全局或静态对象的引用将在编译后的二进制文件中的易失性写入之前发生。

读取volatile对象(volatile read)具有Acquire语义; 在经过编译的二进制文件中的易失性读取之后,在指令序列中读取易失性存储器之后发生的对全局或静态对象的引用。

但是,您可能会注意到,如果您按照上面的链接进行操作,那么在这种情况下,在注释中是否存在获取/释放语义实际上存在争议。

挥发性有时是有用的,原因如下:此代码:

 /* global */ bool flag = false; while (!flag) {} 

被gcc优化为:

 if (!flag) { while (true) {} } 

如果该标志被另一个线程写入,这显然是不正确的。 请注意,如果没有这种优化,同步机制可能会起作用(取决于其他代码,可能需要一些内存屏障) – 在1个生产者 – 1个消费者场景中不需要互斥。

否则,volatile关键字太奇怪了,无法使用 – 它不提供任何内存顺序保证,包括volatile和non-volatile访问,并且不提供任何primefaces操作 – 也就是说,除非禁用寄存器caching。

你需要挥发性,可能locking。

volatile会告诉优化器,这个值可以asynchronous地改变

 volatile bool flag = false; while (!flag) { /*do something*/ } 

会在循环中每次读取标志。

如果您closures优化或者使每个variables变得不稳定,则程序将performance相同但较慢。 不稳定只是意味着“我知道你可能刚刚读过它,知道它说了什么,但是如果我说读它然后阅读它。

locking是程序的一部分。 所以,顺便说一下,如果你正在实施信号量,那么它们必须是不稳定的。 (不要尝试,很难,可能需要一个小的汇编程序或新的primefaces的东西,它已经完成了。)