簡體   English   中英

C ++是從不同的線程編寫和讀取變量的未定義行為

[英]C++ Is writing and reading a variable from different threads undefined behavior

自從我開始多線程以來,我一直在問自己這個問題:

是從不同的線程編寫和讀取變量未定義的行為?

讓我們使用最小的例子,我們在一個線程中遞增一個整數並讀取另一個中的整數。

void thread1()
{
    x++;
}

void thread2()
{
    if (x == 5)
    {
        //doSomething
    }
}

我理解添加操作不是原子的,因此我可以在第一個線程處於添加操作的中間時從第二個線程讀取,但是有些東西我不太確定。

x是否保持其值直到整個加法操作完成然后被賦予此新值,或者x是否具有中間狀態,其中從中讀取將導致未定義的行為。

如果第一個理論適用,那么在寫入時從x讀取只會在添加之前返回值,並且不會出現問題。

如果第二個理論是正確的,那么有人可以更詳細地解釋添加操作的過程是什么以及為什么它將是未定義的行為(可能有一個例子?)

謝謝

評論已經得到了正確的基礎知識。

編譯單個函數時,編譯器可以考慮變量的更改方式。 如果函數不能直接或間接地改變某個變量,那么編譯器可以假設該變量沒有任何變化, 除非有線程同步。 在這種情況下,編譯器必須處理另一個線程更改這些變量的可能性。

如果違反了編譯器假設(即你有一個bug),那么任何事情都可能發生。 這不受限制,因為這會嚴重限制優化器。 你可以假設x在內存中有一些唯一的地址,但是已知優化器可以移動變量並讓多個變量共享一個地址(只是在不同的時間)。 基於單線程假設,這種優化很可能是合理的,這是您的示例違反的假設。 你的第二個線程可能會認為它正在看x ,但也可能會得到y

x(32位變量)將始終在32 +位cpu上定義,但不是那么精確。 您知道x可以是++定義的從開始到結束范圍的任何值。

類似於下面的情況:x被初始化為0並且你調用5次thread1,線程2可以看到這個x在0到5的范圍內。

這意味着我可以考慮將整數分配給內存作為原子。

有兩個原因導致兩個線程上的x不同步,例如,當thread1上的x為5時,thread2上的x可以同時為0。 其中一個原因是cpu cache對於每個核心都是不同的。 要同步緩存之間的值,您必須使用內存屏障。 你可以使用例如std :: atomic ,它可以為你做得很好

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM