2015-05-04 22 views
1

爲什麼C11 atomic_load/atomic_store函數中的參數具有volatile限定符?由於已確定volatile對於併發用例是無用的(例如,1,2)。所有的C11 atomic_load/store和volatile限定符

atomic_load(const volatile A* obj); 
void atomic_store(volatile A* obj , C desired); 

回答

5

首先,你的假設是錯誤的,volatile也不是一無是處,它是不足夠的,這是一個不同的事情。

您引用的接口必須具有volatile限定,否則它們不適用於具有此限定條件的對象。

現在volatile是C11的一個難題,因爲目前存在爭議,如果它僅在對象本身是volatile限定的或只有當前訪問的類型有效。但是可以肯定的是,這裏的_Atomic對象的規則與其他對象沒有多大區別。因此,如果您有一個非修改的非volatile訪問權限,編譯器可以優化訪問權限並依賴以前已知的值。

只有這樣的操作,您可以使用一個_Atomic辦正在評估它:

_Atomic size_t counter = ATOMIC_VAR_INIT(0); 

++counter;   // safe: sequential consistency 
... 
printf("counter: %zu\n", counter); // may use some previous value 
... 
printf("counter: %zu\n", atomic_load(&counter)); // should use actual value 

現在的「應該」在這裏是因爲關於我上面提到volatile不同的解釋。如果您想確保沒有發生負載優化,則應始終聲明_Atomic對象volatile。它不會傷害太多,但可能有助於在一些角落案件。

-2

語義原子操作意味着有多個併發線程訪問變量值。這就是volatile說明符的用途。

您提供的兩個參考文獻都非常有問題,並且通常不適用(通常在SW工程中)。如果您有數據,可以在軟件中同時訪問/修改數據,則必須是volatile

有用例,其中volatile是絕對必要的:內核驅動程序。您不能讓編譯器優化對映射到設備的內存區域的訪問。

有很多基於volatile的編程範例。例如,只有在快速鎖定失敗時,正常關鍵部分/互斥鎖才使用volatile變量快速鎖定並回退到信號/事件/等。

+0

跨線程的共享變量不*具有* volatile *。 volatile的使用通常與多線程無關。 'volatile'意味着對象的值可以在沒有對實現的控制的情況下進行更改,因此,編譯器不會在序列點之間執行訪問優化(雖然它們允許在序列點之間)。這就是爲什麼它對驅動程序編程有用,但它與多線程的關係不存在。線程間的共享變量需要與互斥鎖或類似的鎖定基元同步。 –

+0

@FilipeGonçalves跨變量同步不會消除優化。示例是循環:如果您有一個循環退出變量,並且它不是易失性的,則編譯器可以完全優化對其的訪問。 –