繁体   English   中英

在WinAPI线程之间的共享变量中使用volatile

[英]Using volatile for a shared variable between WinAPI threads

C ++编译器对线程一无所知,C ++编译器仅将“线程”视为函数。

现在说我有两个线程/函数,并且我有一个全局变量。

如果我要在这两个线程/函数中访问全局变量,则C ++编译器可以优化这两个线程中的变量访问代码,然后将全局变量复制到寄存器中,然后开始操作该寄存器而不是内存位置。 现在,由于每个线程都有一组唯一的寄存器,因此,如果这两个线程同时运行,则它们将不会访问内存中的全局变量,而是每个线程都在操纵自己的寄存器!

因此,如果我将全局变量设置为volatile ,那么这将告诉C ++编译器不要优化该变量的访问代码,而始终直接访问内存位置。

这个对吗?

是。 不会吧

在现代的,标准的,跨平台的c ++ volatile中,既不需要不足以实现您正在做的事情。 只是因为您告诉编译器不要优化读取,您才没有告诉CPU /内存不应对读取/写入进行重新排序。 该标准还规定,在您可能还在写信的同时从某处读取是不确定的行为 由于x86 / x64的内存模型过强,您可能会放弃它,但是您不应该冒险。 volatile是供驱动程序和操作系统与硬件对话的。

您应该使用std::atomic<...> 您可以安全地同时读取和写入std::atomic并且不会优化读取/写入*。 它只是正确的选择。

但是...如果您是专门为Windows编写的并且使用的是Visual Studio,那么当使用volatile时,该编译器将提供其他保证,在您使用合适的编译器选项的情况下,它们将起作用。 VS增加了对volatile的保证强度,类似于C#和Java使用volatile的保证。 这意味着在您的情况下它将起作用。 在最新版本的VS上,您可以通过/ volatile编译器选项控制此行为。 但是,除非有必要,否则我不建议您这样做。 除非没有选择,否则请使用标准的std :: atomic。

请注意,C ++ / Java和VS的volatile扩展实际上比使用std::atomic弱。 std::atomic的保证顺序一致性 ,Java和C#都不做,这意味着Dekkers算法可以与std :: atomic一起使用。

* std::atomic实际上可以被优化,但前提是您不能根据准入规则注意到。 这是它们比volatile更好的另一个原因,因为它破坏了优化,因为即使没有必要,编译器也无法推理,即使必须这样做也必须这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM