gpt4 book ai didi

c++ - 将 volatile 用于 WinAPI 线程之间的共享变量

转载 作者:行者123 更新时间:2023-11-28 06:12:44 25 4
gpt4 key购买 nike

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 algorithm可以与 std::atomic 一起使用。

* std::atomic的 实际上可以被优化掉,但前提是你不可能在 as-if 规则下注意到。这是它们优于 volatile 的另一个原因。这会破坏优化,因为它必须简单地完成,即使不必要,因为编译器无法推理。

关于c++ - 将 volatile 用于 WinAPI 线程之间的共享变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30935745/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com