c/c++中所有的操作預設為非原子操作。非原子操作,並不保證操作的完整性。當乙個操作由2個以上的指令完成時,操作可能只執行了乙個指令,變數就被另外乙個執行緒搶占。當多個執行緒同時讀寫同乙個變數時,就會發生資料競爭。
uint64_t i = 0;
void foo()
上述簡單的賦值語句,通過乙個32位的系統編譯,這個操作就需要分別負責高32位和低32位的兩條指令來完成。對於非原子的這兩條指令,任意執行緒都可以在它們期間去訪問變數。
當乙個執行緒搶占在這兩個指令之間呼叫變數,變數只修改了低32位就被其他執行緒呼叫,此時會發生寫撕裂。
讀取情況與賦值情況類似,當乙個執行緒搶占兩個讀取指令之間去修改變數,此時變數只讀取了低32位,此時會發生讀撕裂。
多個執行緒同時呼叫同乙個變數,當其中乙個執行緒執行寫操作時,必須使用原子型別。
原子型別的操作屬於原子操作,對於它們的操作只有2種狀態,完成和不做。不會出現操作進行一半而被其他執行緒搶占的情況。
#include #include #include bool x=false; // x現在是乙個非原子變數
std::atomicy;
std::atomicz;
void write_x_then_y()
void read_y_then_x()
int main()
上述**,實現原子型別來對非原子型別操作排序的的功能。是否可以將原子變數y替換為非原子變數呢?答案是否定的。
對於變數y,執行緒a和執行緒b會同時進行訪問,執行緒b不斷讀取等待執行緒a將y值修改。當變數y為非原子型別時,該**就會發生資料競爭,引發「未定義行為」。
當使用原子型別進行操作排序時,「自由」記憶體順序和非原子型別的操作順序就等價了,可以將「自由」記憶體順序的變數,直接替換為非原子型別。
java併發程式設計基礎 原子類與原子更新
1 什麼是原子類 原子類可以認為其操作都是不可分割 2 為什麼要有原子類 對多執行緒訪問同乙個變數,我們需要加鎖,而鎖是比較消耗效能的,jdk1.5之後,新增的原子操作類提供了一種用法簡單 效能高效 執行緒安全地更新乙個變數的方式,這些類同樣位於juc包下的atomic包下,發展到jdk1.8,該包...
C 程式設計 基礎語法02 資料與型別
運算子與表示式 型別 資料型別 只要是資料就有數值與型別 資料必定屬於某一型別,沒有型別的資料是沒有意義的,是不存在的!1 常量是資料 10是資料,10.1是資料,a 是資料,aabb 是資料 2 變數是資料 變數是用來儲存資料的,所以變數當然是資料 3 表示式是資料 表示式是用來運算資料的,所以表...
《C 的程式設計》 資料型別與表示式
目的 1.掌握c 語言資料型別,熟悉如何定義變數,以及變數賦值的方法 2.學會使用c 有關算術運算子,以及包含這些運算子的表示式 3.進一步熟悉c 程式的結構 4.進一步熟悉c 程式的編輯 編譯 連線和執行的過程。c 程式設計課後題 3.includeusing namespace std int ...