[英]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.