原子操作 |
原子操作是一類不可分割的操作,當操作在任意線程中進行一半時,是不能被查看;它的狀態要么是完成,要么是未完成。如果從對象中讀取一個值的操作是原子的,並且對對象的所有修改也都是原子的話,那么加載操作要么會檢索到對象初始化值,要么就將值存在某一次修改中。非原子操作可能會被視為由一個線程完成一半的操作。如果是一個存儲操作,那么其他線程看到的,可能既不是存儲前的值,也可能不是已存儲的值;如果非原子操作是一個加載操作,那么它可能會去檢索對象的部分成員,或是在另一個線程修改了對象的 值后,對對象進行檢索;所以,檢索出來的值可能既不是第一個值,也不是第二個值,可能是某種兩者結合的值,會構成數據競爭,且會伴有有未定義行為。 |
原子類型/相關特化類 |
atomic_bool/ std::atomic<bool> atomic_char/ std::atomic<char> atomic_schar/ std::atomic<signed char> atomic_uchar/ std::atomic<unsigned char> atomic_int/ std::atomic<int> atomic_uint/ std::atomic<unsigned> atomic_short/ std::atomic<short> atomic_ushort/ std::atomic<unsigned short> atomic_long/ std::atomic<long> atomic_ulong/ std::atomic<unsigned long> atomic_llong/ std::atomic<long long> atomic_ullong/ std::atomic<unsigned long long> atomic_char16_t/ std::atomic<char16_t> atomic_char32_t/ std::atomic<char32_t> atomic_wchar_t/ std::atomic<wchar_t> |
atomic_flag |
最簡單的標准原子類型,表示一個布爾標志。該類型對象可以在兩個狀態間切換:設置和清除。std::atomic_flag 類型的對象必須被ATOMIC_FLAG_INIT初始化。初始化標志位是“清除”狀態。std::atomic_flag 類型不提供is_lock_free()成員函數 |
相關操作 |
clear() store() -- std::atomic<bool> b; bool x=b.load(std::memory_order_acquire); b.store(true); x=b.exchange(false, std::memory_order_acq_rel);
-- compare_exchange_weak() compare_exchange_strong()
bool expected=false; extern atomic<bool> b; // 設置些什么 while(!b.compare_exchange_weak(expected,true) && !expected); |
std::atomic指針運算 |
原子指針類型,可以使用內置類型或自定義類型T,通過特化 std::atomic<T*> 進行定義,就如同使用bool類型定義 std::atomic<bool> 類型一樣。雖然接口幾乎一致,但是它的操作是對於相關的類型的指針,而非bool值本身。就像 std::atomic<bool> ,雖然它既不能拷貝構造,也不能拷貝賦值,但是他可以通過合適的類型指針進行構造和賦值。如同成員函數is_lock_free()一樣, std::atomic<T*> 也有load(), store(), exchange(), compare_exchange_weak()和compare_exchage_strong()成員函數, 與 std::atomic<bool> 的語義相同,獲取與返回的類型都是T*,而不是bool。 |
原子類型支持的操作 |
![]() |
原子實現的spinlock_mutex |
class spinlock_mutex { std::atomic_flag flag; public: spinlock_mutex():flag(ATOMIC_FLAG_INIT) {} void lock(){ while(flag.test_and_set(std::memory_order_acquire)); } void unlock(){ flag.clear(std::memory_order_release); } }; |