簡體   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