青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

路漫漫,長(zhǎng)修遠(yuǎn),我們不能沒有錢
隨筆 - 173, 文章 - 0, 評(píng)論 - 257, 引用 - 0
數(shù)據(jù)加載中……

C++ Atomic

C++ Atomic

atomic 是STL(標(biāo)準(zhǔn)庫)中的一個(gè)頭文件, 定義了 C++11標(biāo)準(zhǔn)中的一些表示 線程并發(fā)控制 時(shí) 原子操作 的類與方法. 主要聲明了兩個(gè)類模板: std::atomic 和 std::atomic_flag, 另外還聲明了一套C風(fēng)格的原子類型 與 C兼容的原子操作的函數(shù).

在多線程并發(fā)執(zhí)行時(shí), 原子操作 是線程不會(huì)打斷的執(zhí)行片段. 一些程序設(shè)計(jì)更為注重性能和效率, 需要開發(fā) lock-free 的算法與數(shù)據(jù)結(jié)構(gòu), 這就需要更為底層的 原子操作 與 原子類型原子類型對(duì)象的主要特點(diǎn)就是從不同的線程并發(fā)訪問是 良性(well-defined) 行為, 不會(huì)導(dǎo)致 競(jìng)爭(zhēng)危害. 與之相反, 不做適當(dāng)控制就并發(fā)訪問 非原子對(duì)象 則會(huì)導(dǎo)致 未定義(undefined) 行為.

內(nèi)存序模型

僅靠原子指令實(shí)現(xiàn)不了對(duì)資源的訪問控制. 這造成的原因是編譯器和cpu實(shí)施了重排指令, 導(dǎo)致讀寫順序會(huì)發(fā)生變化, 只要不存在依賴, 代碼中后面的指令可能會(huì)被放在前面, 從而先執(zhí)行它. cpu這么做是為了盡量塞滿每個(gè)時(shí)鐘周期, 在單位時(shí)間內(nèi)盡量執(zhí)行更多的指令, 從而提高吞吐率.

我們先來看兩個(gè)線程代碼:

// thread 1 // flag初始值為false     a.init();     flag = true;
// thread 2     if(flag) {         a.bar();     }

線程2在ready為true的時(shí)候會(huì)訪問p, 對(duì)線程1來說, 如果按照正常的執(zhí)行順序, 那么p先被初始化, 然后在將ready賦為true. 但對(duì)多核的機(jī)器而言, 情況可能有所變化:

  • 線程1中的 ready = true 可能會(huì)被CPU或編譯器 重排序 到 p.init() 的前面, 從而優(yōu)先執(zhí)行 ready = true 這條指令. 在線程2中, p.bar() 中的一些代碼可能被重排到 if(ready) 之前.
  • 即使沒有 重排序, ready和p的值也會(huì)獨(dú)立地同步到線程2所在核心的cache, 線程2仍然可能在看到ready為true時(shí)看到未初始化的p.

為了解決這個(gè)問題, 我們一種解決方法是使用互斥元, 還有一種就是CPU和編譯器提供了memory fence, 讓用戶可以聲明訪存指令的可見性關(guān)系, C++11總結(jié)為以下memory order

內(nèi)存序模型 是討論在 原子操作 附近的 讀寫 操作順序

// c++11  ~~  c++17
typedef enum memory_order {
memory_order_relaxed,
memory_order_consume,
memory_order_acquire,
memory_order_release,
memory_order_acq_rel,
memory_order_seq_cst
} memory_order;
//c++20
enum class memory_order : /*unspecified*/ {
relaxed, consume, acquire, release, acq_rel, seq_cst
};
inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
inline constexpr memory_order memory_order_consume = memory_order::consume;
inline constexpr memory_order memory_order_acquire = memory_order::acquire;
inline constexpr memory_order memory_order_release = memory_order::release;
inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
  • memory_order_relaxed: 只保證 原子操作 的 原子性 .

    fencing作用, CPU和編譯器 可以 重排序 指令

  • memory_order_consume: 使用這種 內(nèi)存序 的  操作在被影響的內(nèi)存位置上執(zhí)行consume操作:

    • 當(dāng)前線程依賴于這個(gè)當(dāng)前 讀取值的 讀寫 操作 不能 重排序 到這條  操作之前;
    • 這個(gè) 原子變量 的其他線程的數(shù)據(jù)依賴變量的 寫入 對(duì)當(dāng)前線程 可見 .
    • 在大多數(shù)平臺(tái), 這 只影響 編譯器的行為.

    后面 依賴此 原子變量 的訪存指令 不能 重排序 至此條指令之前

  • memory_order_acquire: 使用這種 內(nèi)存序 的  操作在被影響的內(nèi)存位置上執(zhí)行acquire操作:

    • 當(dāng)前線程的 讀寫 不能 被 重排序 在這條  操作之前.
    • 其他線程對(duì)這個(gè)原子變量的所有  操作對(duì)當(dāng)前線程是 可見 的.

    后面 依賴此 原子變量 的訪存指令 不能 重排序 至此條指令之前

  • memory_order_release: 使用這種 內(nèi)存序 的  操作在被影響的內(nèi)存位置上執(zhí)行release操作:

    • 當(dāng)前線程的 讀寫 不能被 重排序 在這條  操作之后.
    • 當(dāng)前線程的所有  操作對(duì)其他  這個(gè) 原子變量 的線程是 可見 的.
    • 導(dǎo)致這個(gè) 原子變量 依賴的  操作對(duì)于其他 consume 這個(gè) 原子變量 的線程是 可見 的.

    前面 依賴此 原子變量 的訪存指令 不能 重排序 到此條指令之后. 當(dāng)此條指令的結(jié)果被同步到其他核的cache中時(shí), 保證前面的指令也已經(jīng)被同步.

  • memory_order_acq_rel: 使用這種 內(nèi)存序 的一個(gè) read-modify-write 操作既是 acquire 操作也是 release 操作. 當(dāng)前線程的 讀寫 不能 被 重排序 在這條操作之前以及之后. 其他線程對(duì)這個(gè) 原子變量 的 release 對(duì)本線程是 可見 的. 本線程的這條操作結(jié)果對(duì)其他 讀取 該 原子變量 的線程是 可見 的.

    acquare + release

  • memory_order_seq_cst: 使用這種 內(nèi)存序 的  操作在被影響的內(nèi)存位置上執(zhí)行 acquire 操作, 使用這種 內(nèi)存序 的  操作在被影響的內(nèi)存位置上執(zhí)行 release 操作, 使用這種 內(nèi)存序 的一個(gè) read-modify-write 操作既是 acquire 操作也是 release 操作. 并存在一個(gè)全序, 所有線程看到的所有修改是同樣的順序.

    acquare + release + 所有使用 memory_order_seq_cst 的指令有嚴(yán)格的全序關(guān)系

有了 memory_order, 我們可以這么改上面的例子:

// thread 1 // flag初始值為false     a.init();     flag.store(true, std::memory_order_release);  //前面的不能在我后面執(zhí)行
// thread 2     if(flag.load(std::memory_order_acquire)) {   //后面的不能在我前面執(zhí)行         a.bar();     }

這樣就保證了線程1和線程2的順序性, 比如線程2在看到flag==true時(shí), 能看到線程1 realse之前所有操作. 也就保證了代碼符合我們的預(yù)期.

注意 : memory fence(內(nèi)存柵欄) 不等于可見性, 即使線程2恰好在線程1在把flag設(shè)置為true后讀取了flag也不意味著它能看到true, 因?yàn)橥絚ache是有延時(shí)的. memory fence保證的是可見性的順序: "假如我看到了a的最新值, 那么我一定也得看到b的最新值".

atomic_flag類型

atomic_flag 是一種簡(jiǎn)單的原子布爾類型, 只支持兩種操作: test_and_set 和 clear.

結(jié)合 std::atomic_flag::test_and_set() 和 std::atomic_flag::clear()std::atomic_flag 對(duì)象可以當(dāng)作一個(gè)簡(jiǎn)單的自旋鎖(spin lock)使用.

構(gòu)造函數(shù)

atomic_flag() noexcept = default;           //只有默認(rèn)構(gòu)造函數(shù)
atomic_flag (const atomic_flag&T) = delete; //禁用拷貝構(gòu)造函數(shù)

移動(dòng)構(gòu)造函數(shù)實(shí)際上也禁用. 根據(jù)C++標(biāo)準(zhǔn)的一般規(guī)定, 如果一個(gè)類顯式聲明了拷貝構(gòu)造函數(shù)(即使是作為delete), 就不會(huì)有缺省的移動(dòng)構(gòu)造函數(shù).
相關(guān)的宏:如果在初始化時(shí)沒有明確使用宏ATOMIC_FLAG_INIT初始化, 那么新創(chuàng)建的std::atomic_flag 對(duì)象的狀態(tài)是 未指定的(unspecified), 既沒有被 set 也沒有被 clear ; 如果使用該宏初始化, 該 std::atomic_flag 對(duì)象在創(chuàng)建時(shí)處于 clear 狀態(tài).

成員函數(shù)

//返回該std::atomic_flag對(duì)象當(dāng)前狀態(tài),如果當(dāng)前狀態(tài)為false則設(shè)置(set) 該對(duì)象為true. 該函數(shù)是原子的
bool test_and_set (memory_order sync = memory_order_seq_cst) volatile noexcept;
bool test_and_set (memory_order sync = memory_order_seq_cst) noexcept;
//清除std::atomic_flag 對(duì)象的標(biāo)志位, 即設(shè)置atomic_flag 的值為false
void clear (memory_order sync = memory_order_seq_cst) volatile noexcept;
void clear (memory_order sync = memory_order_seq_cst) noexcept;

示例

#include <iostream>  #include <atomic>  #include <vector>  #include <thread>  #include <sstream> 
std::atomic_flag 
lock = ATOMIC_FLAG_INIT;    std::stringstream stream; 
int main() {     std::vector<std::thread> vec_thread;      for ( int i = 0; i < 10; i++ ) {         vec_thread.push_back( std::thread( [](int x){             while ( lock.test_and_set() );              stream << "thread#" << x << " \n ";                   lock.clear();         }, i));      }
    
for ( int i = 0; i < 10; i++ ){          vec_thread[i].join();     }
    std::cout 
<< stream.str();       return 0;  }

基于std::atom_flag類的C風(fēng)格API

bool atomic_flag_test_and_set (volatile atomic_flag* obj) noexcept;
bool atomic_flag_test_and_set (atomic_flag* obj) noexcept;
bool atomic_flag_test_and_set (volatile atomic_flag* obj, memory_order sync) noexcept;
bool atomic_flag_test_and_set (atomic_flag* obj, memory_order sync) noexcept;
void atomic_flag_clear (volatile atomic_flag* obj) noexcept;
void atomic_flag_clear (atomic_flag* obj) noexcept;
void atomic_flag_clear (volatile atomic_flag* obj, memory_order sync) noexcept;
void atomic_flag_clear (atomic_flag* obj, memory_order sync) noexcept;

std::atomic類模板

std::atomic 比 std::atomic_flag 功能更加完善, 因此有更多的成員方法.

template < class T > struct atomic {
    
// 缺省構(gòu)造,  std::atomic 對(duì)象處于未初始化(uninitialized)狀態(tài)     atomic() = default
    
// 普通構(gòu)造函數(shù), 由類型T初始化一個(gè) std::atomic對(duì)象     constexpr atomic(T)) noexcept; 
    
// 禁止拷貝構(gòu)造     atomic(const atomic &= delete; 
    
// 禁止拷貝賦值     atomic & operator=(const atomic &= delete;      atomic & operator=(const atomic &volatile = delete;
    
// 從類型T的隱式轉(zhuǎn)換賦值     T operator=(T) volatile noexcept;      T operator=(T) noexcept;

    
// 判斷該 std::atomic對(duì)象是否具備lock-free的特性. 如果某個(gè)對(duì)象滿足 lock-free 特性, 在多個(gè)線程訪問該對(duì)象時(shí)不會(huì)導(dǎo)致線程阻塞.      bool is_lock_free() const volatile;      bool is_lock_free() const;

    
// 修改被封裝的值, 參數(shù) sync 指定內(nèi)存序     void store(T, memory_order = memory_order_seq_cst) volatile;     void store(T, memory_order = memory_order_seq_cst);

    
// 讀取被封裝的值, 參數(shù) sync 設(shè)置內(nèi)存序     T load(memory_order = memory_order_seq_cst) const volatile;     T load(memory_order = memory_order_seq_cst) const;
    
// 與load()的功能類似, 也是讀取被封裝的值     operator T() const volatile;      operator T() const;
    
// 讀取并修改被封裝的值, 用val指定的值替換該原子對(duì)象封裝的值, 并返回該原子對(duì)象之前封裝的值, 整個(gè)過程是原子的, 因此exchange 操作也稱為 read-modify-write 操作.     T exchange(T, memory_order = memory_order_seq_cst) volatile;     T exchange(T, memory_order = memory_order_seq_cst);
    
// 比較被封裝的值(weak)與參數(shù)expected所指定的值的物理內(nèi)容是否相等, 如果相等, 則用val替換原子對(duì)象的舊值;如果不相等, 則用原子對(duì)象的舊值替換expected.     // 因此調(diào)用該函數(shù)之后, 如果被該原子對(duì)象封裝的值與參數(shù) expected 所指定的值不相等, expected 中的內(nèi)容就是原子對(duì)象的舊值.      // 整個(gè)操作是原子的, 當(dāng)前線程讀取和修改該原子對(duì)象時(shí), 別的線程不能對(duì)讀取和修改該原子對(duì)象.      // 與compare_exchange_strong不同, weak版本的compare-and-exchange操作允許spuriously 返回 false, 即原子對(duì)象所封裝的值與參數(shù) expected 的物理內(nèi)容相同, 但卻仍然返回 false, 這在使用循環(huán)操作的算法下是可以接受的, 并且在一些平臺(tái)下weak版本的性能更     bool compare_exchange_weak (T& expected, T val, memory_order sync = memory_order_seq_cst) volatile noexcept;     bool compare_exchange_weak (T& expected, T val, memory_order sync = memory_order_seq_cst) noexcept;
    
// 功能同上. 內(nèi)存序(Memory Order)的選擇取決于比較操作結(jié)果, 如果比較結(jié)果為 true(即原子對(duì)象的值等于 expected), 則選擇參數(shù) success 指定的內(nèi)存序, 否則選擇參數(shù) failure 所指定的內(nèi)存序.     bool compare_exchange_weak (T& expected, T val,  memory_order success, memory_order failure) volatile noexcept;     bool compare_exchange_weak (T& expected, T val, memory_order success, memory_order failure) noexcept;
    
// 與weak版本的差別在于, 如果原子對(duì)象所封裝的值與參數(shù) expected 的物理內(nèi)容相同, 比較操作一定會(huì)為 true.      bool compare_exchange_strong(T &, T, memory_order = memory_order_seq_cst) volatile;      bool compare_exchange_strong(T &, T, memory_order = memory_order_seq_cst);     bool compare_exchange_strong(T &, T, memory_order, memory_order) volatile;     bool compare_exchange_strong(T &, T, memory_order, memory_order);
};

C++11標(biāo)準(zhǔn)庫std::atomic提供了針對(duì)整形(integral)和指針類型的特化實(shí)現(xiàn).

針對(duì)整形(integal)的特化, 其中integal 代表了如下類型 charsigned charunsigned charshortunsigned shortintunsigned intlongunsigned longlong longunsigned long longchar16_tchar32_twchar_t :

template <> struct atomic<integral> {     bool is_lock_free() const volatile;     bool is_lock_free() const;
    
void store(integral, memory_order = memory_order_seq_cst) volatile;     void store(integral, memory_order = memory_order_seq_cst);
    integral load(memory_order 
= memory_order_seq_cst) const volatile;     integral load(memory_order = memory_order_seq_cst) const;
    
operator integral() const volatile;     operator integral() const;
    integral exchange(integral, memory_order 
= memory_order_seq_cst) volatile;     integral exchange(integral, memory_order = memory_order_seq_cst);
    
bool compare_exchange_weak(integral&, integral, memory_order, memory_order) volatile;     bool compare_exchange_weak(integral&, integral, memory_order, memory_order);
    
bool compare_exchange_strong(integral&, integral, memory_order, memory_order) volatile;     bool compare_exchange_strong(integral&, integral, memory_order, memory_order);
    
bool compare_exchange_weak(integral&, integral, memory_order = memory_order_seq_cst) volatile;     bool compare_exchange_weak(integral&, integral, memory_order = memory_order_seq_cst);
    
bool compare_exchange_strong(integral&, integral, memory_order = memory_order_seq_cst) volatile;     bool compare_exchange_strong(integral&, integral, memory_order = memory_order_seq_cst);
    
//原子對(duì)象的封裝值加 val, 并返回原子對(duì)象的舊值. 整個(gè)過程是原子的     integral fetch_add(integral, memory_order = memory_order_seq_cst) volatile;     integral fetch_add(integral, memory_order = memory_order_seq_cst);
    integral fetch_sub(integral, memory_order 
= memory_order_seq_cst) volatile;     integral fetch_sub(integral, memory_order = memory_order_seq_cst);
    integral fetch_and(integral, memory_order 
= memory_order_seq_cst) volatile;     integral fetch_and(integral, memory_order = memory_order_seq_cst);
    integral fetch_or(integral, memory_order 
= memory_order_seq_cst) volatile;     integral fetch_or(integral, memory_order = memory_order_seq_cst);
    integral fetch_xor(integral, memory_order 
= memory_order_seq_cst) volatile;     integral fetch_xor(integral, memory_order = memory_order_seq_cst);
    atomic() 
= default;     constexpr atomic(integral);     atomic(const atomic&= delete;
    atomic
& operator=(const atomic&= delete;     atomic& operator=(const atomic&volatile = delete;
    integral 
operator=(integral) volatile;     integral operator=(integral);
    integral 
operator++(intvolatile//后綴++     integral operator++(int);
    integral 
operator--(intvolatile//后綴--     integral operator--(int);
    integral 
operator++() volatile//前綴++     integral operator++();
    integral 
operator--() volatile//前綴--     integral operator--();
    integral 
operator+=(integral) volatile;     integral operator+=(integral);
    integral 
operator-=(integral) volatile;     integral operator-=(integral);
    integral 
operator&=(integral) volatile;     integral operator&=(integral);
    integral 
operator|=(integral) volatile;     integral operator|=(integral);
    integral 
operator^=(integral) volatile;     integral operator^=(integral); };

針對(duì)指針的特化:

template <class T> struct atomic<T*> {     bool is_lock_free() const volatile;     bool is_lock_free() const;
    
void store(T*, memory_order = memory_order_seq_cst) volatile;     void store(T*, memory_order = memory_order_seq_cst);
    T
* load(memory_order = memory_order_seq_cst) const volatile;     T* load(memory_order = memory_order_seq_cst) const;
    
operator T*() const volatile;     operator T*() const;
    T
* exchange(T*, memory_order = memory_order_seq_cst) volatile;     T* exchange(T*, memory_order = memory_order_seq_cst);
    
bool compare_exchange_weak(T*&, T*, memory_order, memory_order) volatile;     bool compare_exchange_weak(T*&, T*, memory_order, memory_order);
    
bool compare_exchange_strong(T*&, T*, memory_order, memory_order) volatile;     bool compare_exchange_strong(T*&, T*, memory_order, memory_order);
    
bool compare_exchange_weak(T*&, T*, memory_order = memory_order_seq_cst) volatile;     bool compare_exchange_weak(T*&, T*, memory_order = memory_order_seq_cst);
    
bool compare_exchange_strong(T*&, T*, memory_order = memory_order_seq_cst) volatile;     bool compare_exchange_strong(T*&, T*, memory_order = memory_order_seq_cst);
    T
* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst) volatile;     T* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst);
    T
* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst) volatile;     T* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst);
    atomic() 
= default;     constexpr atomic(T*);     atomic(const atomic&= delete;
    atomic
& operator=(const atomic&= delete;     atomic& operator=(const atomic&volatile = delete;
    T
* operator=(T*volatile;     T* operator=(T*);
    T
* operator++(intvolatile;     T* operator++(int);
    T
* operator--(intvolatile;     T* operator--(int);
    T
* operator++() volatile;     T* operator++();
    T
* operator--() volatile;     T* operator--();
    T
* operator+=(ptrdiff_t) volatile;     T* operator+=(ptrdiff_t);
    T
* operator-=(ptrdiff_t) volatile;     T* operator-=(ptrdiff_t); };

范例

#include <iostream> #include <atomic> #include <vector> #include <thread> #include <sstream>
std::atomic
<int> foo(0);
void set_foo(int x){     foo = x; }
void print_foo(){     while (foo == 0) {         std::this_thread::yield();     }     std::cout << "x: " << foo << std::endl; }
int main() {     std::thread print_th(print_foo);     std::thread set_th(set_foo, 10);     print_th.join();     set_th.join();     return 0; }

基于std::atomic 類模板的C風(fēng)格API

template <class T> bool atomic_is_lock_free (const volatile atomic<T>* obj) noexcept;
template <class T> bool atomic_is_lock_free (const atomic<T>* obj) noexcept;
bool atomic_is_lock_free (const volatile A* obj) noexcept;
bool atomic_is_lock_free (const A* obj) noexcept;
//初始化原子對(duì)象. 如果對(duì)一個(gè)已初始化的原子對(duì)象再次調(diào)用 atomic_init(), 則會(huì)導(dǎo)致未定義行為(undefined behavior)
template <class T> void atomic_init (volatile atomic<T>* obj, T val) noexcept;
template <class T> void atomic_init (atomic<T>* obj, T val) noexcept;
void atomic_init (volatile A* obj, T val) noexcept;
void atomic_init (A* obj, T val) noexcept;
template <class T> void atomic_store (volatile atomic<T>* obj, T val) noexcept;
template <class T> void atomic_store (atomic<T>* obj, T val) noexcept;
void atomic_store (volatile A* obj, T val) noexcept;
void atomic_store (A* obj, T val) noexcept;
template <class T> T atomic_load (const volatile atomic<T>* obj) noexcept;
template <class T> T atomic_load (const atomic<T>* obj) noexcept;
T atomic_load (const volatile A* obj) noexcept;
T atomic_load (const A* obj) noexcept;
template <class T> T atomic_load_explicit (const volatile atomic<T>* obj, memory_order sync) noexcept;
template <class T> T atomic_load_explicit (const atomic<T>* obj, memory_order sync) noexcept;
T atomic_load_explicit (const volatile A* obj, memory_order sync) noexcept;
T atomic_load_explicit (const A* obj, memory_order sync) noexcept;
template <class T> T atomic_exchange (volatile atomic<T>* obj, T val) noexcept;
template <class T> T atomic_exchange (atomic<T>* obj, T val) noexcept;
T atomic_exchange (volatile A* obj, T val) noexcept;
T atomic_exchange (A* obj, T val) noexcept;
template <class T> T atomic_store_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
template <class T> T atomic_store_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
T atomic_store_explicit (volatile A* obj, T val, memory_order sync) noexcept;
T atomic_store_explicit (A* obj, T val, memory_order sync) noexcept;
template <class T> bool atomic_compare_exchange_weak (volatile atomic<T>* obj, T* expected, T val) noexcept;
template <class T> bool atomic_compare_exchange_weak (atomic<T>* obj, T* expected, T val) noexcept;
bool atomic_compare_exchange_weak (volatile A* obj, T* expected, T val) noexcept;
bool atomic_compare_exchange_weak (A* obj, T* expected, T val) noexcept;
template <class T> bool atomic_compare_exchange_weak_explicit (volatile atomic<T>* obj,T* expected, T val, memory_order success, memory_order failure) noexcept;
template <class T> bool atomic_compare_exchange_weak_explicit (atomic<T>* obj,T* expected, T val, memory_order success, memory_order failure) noexcept;
bool atomic_compare_exchange_weak_explicit (volatile A* obj,T* expected, T val, memory_order success, memory_order failure) noexcept;
bool atomic_compare_exchange_weak_explicit (A* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;
template <class T> bool atomic_compare_exchange_strong (volatile atomic<T>* obj, T* expected, T val) noexcept;
template <class T> bool atomic_compare_exchange_strong (atomic<T>* obj, T* expected, T val) noexcept;
bool atomic_compare_exchange_strong (volatile A* obj, T* expected, T val) noexcept;
bool atomic_compare_exchange_strong (A* obj, T* expected, T val) noexcept;
template <class T> bool atomic_compare_exchange_strong_explicit (volatile atomic<T>* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;
template <class T> bool atomic_compare_exchange_strong_explicit (atomic<T>* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;
bool atomic_compare_exchange_strong_explicit (volatile A* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;
bool atomic_compare_exchange_strong_explicit (A* obj, T* expected, T val, memory_order success, memory_order failure) noexcept;
template <class T> T atomic_fetch_add (volatile atomic<T>* obj, T val) noexcept;
template <class T> T atomic_fetch_add (atomic<T>* obj, T val) noexcept;
template <class U> U* atomic_fetch_add (volatile atomic<U*>* obj, ptrdiff_t val) noexcept;
template <class U> U* atomic_fetch_add (atomic<U*>* obj, ptrdiff_t val) noexcept;
T atomic_fetch_add (volatile A* obj, M val) noexcept;
T atomic_fetch_add (A* obj, M val) noexcept;
template <class T> T atomic_fetch_add_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
template <class T> T atomic_fetch_add_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
template <class U> U* atomic_fetch_add_explicit (volatile atomic<U*>* obj, ptrdiff_t val, memory_order sync) noexcept;
template <class U> U* atomic_fetch_add_explicit (atomic<U*>* obj, ptrdiff_t val, memory_order sync) noexcept;
T atomic_fetch_add_explicit (volatile A* obj, M val, memory_order sync) noexcept;
T atomic_fetch_add_explicit (A* obj, M val, memory_order sync) noexcept;
template <class T> T atomic_fetch_sub (volatile atomic<T>* obj, T val) noexcept;
template <class T> T atomic_fetch_sub (atomic<T>* obj, T val) noexcept;
template <class U> U* atomic_fetch_sub (volatile atomic<U*>* obj, ptrdiff_t val) noexcept;
template <class U> U* atomic_fetch_sub (atomic<U*>* obj, ptrdiff_t val) noexcept;
T atomic_fetch_sub (volatile A* obj, M val) noexcept;
T atomic_fetch_sub (A* obj, M val) noexcept;
template <class T> T atomic_fetch_sub_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
template <class T> T atomic_fetch_sub_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
template <class U> U* atomic_fetch_sub_explicit (volatile atomic<U*>* obj, ptrdiff_t val, memory_order sync) noexcept;
template <class U> U* atomic_fetch_sub_explicit (atomic<U*>* obj, ptrdiff_t val, memory_order sync) noexcept;
T atomic_fetch_sub_explicit (volatile A* obj, M val, memory_order sync) noexcept;
T atomic_fetch_sub_explicit (A* obj, M val, memory_order sync) noexcept;
template <class T> T atomic_fetch_and (volatile atomic<T>* obj, T val) noexcept;
template <class T> T atomic_fetch_and (atomic<T>* obj, T val) noexcept;
T atomic_fetch_and (volatile A* obj, T val) noexcept;
T atomic_fetch_and (A* obj, T val) noexcept;
template <class T> T atomic_fetch_and_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
template <class T> T atomic_fetch_and_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
T atomic_fetch_and_explicit (volatile A* obj, T val, memory_order sync) noexcept;
T atomic_fetch_and_explicit (A* obj, T val, memory_order sync) noexcept;
template <class T> T atomic_fetch_or (volatile atomic<T>* obj, T val) noexcept;
template <class T> T atomic_fetch_or (atomic<T>* obj, T val) noexcept;
T atomic_fetch_or (volatile A* obj, T val) noexcept;
T atomic_fetch_or (A* obj, T val) noexcept;
template <class T> T atomic_fetch_or_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
template <class T> T atomic_fetch_or_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
T atomic_fetch_or_explicit (volatile A* obj, T val, memory_order sync) noexcept;
T atomic_fetch_or_explicit (A* obj, T val, memory_order sync) noexcept;
template <class T> T atomic_fetch_xor (volatile atomic<T>* obj, T val) noexcept;
template <class T> T atomic_fetch_xor (atomic<T>* obj, T val) noexcept;
T atomic_fetch_xor (volatile A* obj, T val) noexcept;
T atomic_fetch_xor (A* obj, T val) noexcept;
template <class T> T atomic_fetch_xor_explicit (volatile atomic<T>* obj, T val, memory_order sync) noexcept;
template <class T> T atomic_fetch_xor_explicit (atomic<T>* obj, T val, memory_order sync) noexcept;
T atomic_fetch_xor_explicit (volatile A* obj, T val, memory_order sync) noexcept;
T atomic_fetch_xor_explicit (A* obj, T val, memory_order sync) noexcept;

附錄

與原子對(duì)象初始化相關(guān)的宏:

  • ATOMIC_VAR_INIT(val):初始化 std::atomic 對(duì)象.
  • ATOMIC_FLAG_INIT:初始化 std::atomic_flag 對(duì)象.

引用記錄

李白的blog
256code

posted on 2022-10-14 16:36 Khan 閱讀(248) 評(píng)論(0)  編輯 收藏 引用


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            一级成人国产| 国产精品高潮视频| 制服丝袜亚洲播放| 99香蕉国产精品偷在线观看| 亚洲国产高清自拍| 久久躁狠狠躁夜夜爽| 久久综合电影一区| 亚洲国产一区二区a毛片| 日韩视频一区二区三区在线播放 | 99国产精品久久久久久久| 夜夜嗨av一区二区三区| 欧美一区二区三区四区在线观看地址| 久久久久亚洲综合| 亚洲破处大片| 欧美亚洲视频| 麻豆精品视频| 欧美三级视频在线观看| 国产视频一区免费看| 1024成人| 亚洲欧洲99久久| 亚洲丰满在线| 香蕉av福利精品导航| 欧美国产先锋| 国内精品福利| 亚洲专区欧美专区| 欧美成人午夜影院| 蜜臀av国产精品久久久久| 另类天堂av| 国产精品久久久久久久第一福利 | 国产欧美精品xxxx另类| 亚洲日本aⅴ片在线观看香蕉| 午夜老司机精品| 亚洲日本无吗高清不卡| 久久激情五月婷婷| 国产精品观看| 99re6热只有精品免费观看| 久久久噜噜噜久久中文字免| 夜夜嗨一区二区三区| 麻豆国产精品777777在线| 国产欧美日韩视频一区二区| 一本色道久久加勒比88综合| 欧美第一黄色网| 久久国产乱子精品免费女 | 欧美福利视频一区| 狠狠综合久久av一区二区老牛| 亚洲伊人久久综合| 亚洲精品国久久99热| 老司机久久99久久精品播放免费| 国产精品女人网站| 亚洲自拍另类| 中文在线资源观看网站视频免费不卡| 免费在线亚洲| 亚洲高清影视| 欧美成人精精品一区二区频| 欧美在线视频a| 国产欧美91| 久久久久久97三级| 久久大逼视频| 亚洲国产精品综合| 亚洲国产va精品久久久不卡综合| 欧美一区二区三区视频免费播放| 日韩特黄影片| 欧美日韩国产综合新一区| 亚洲精选中文字幕| 91久久久一线二线三线品牌| 女人色偷偷aa久久天堂| 亚洲国产精品t66y| 亚洲国产精品久久久久秋霞蜜臀| 久久先锋资源| 亚洲裸体在线观看| 99在线热播精品免费| 国产精品久久久久久久久久尿 | 欧美激情一级片一区二区| 老司机成人网| 亚洲尤物精选| 亚洲欧美日韩第一区| 国产日韩亚洲欧美| 美女脱光内衣内裤视频久久影院| 欧美成人影音| 亚洲美女淫视频| 欧美三日本三级三级在线播放| 亚洲午夜一区| 欧美一区二区私人影院日本 | 欧美一区国产一区| 欧美尤物一区| 亚洲精品一区二区三区樱花| 亚洲精品一区在线观看香蕉| 欧美日韩中文| 久久久精彩视频| 免费视频亚洲| 亚洲尤物在线视频观看| 久久久999精品免费| 亚洲精品在线免费观看视频| 在线午夜精品| 精品电影在线观看| 亚洲激情视频在线播放| 国产精品看片你懂得| 久久久精品动漫| 欧美激情一区二区三区高清视频| 亚洲一区二区三区涩| 欧美一区国产在线| aa亚洲婷婷| 久久精品亚洲一区二区三区浴池| a4yy欧美一区二区三区| 香蕉亚洲视频| 在线亚洲免费| 狼狼综合久久久久综合网| 亚洲欧美另类综合偷拍| 免费看亚洲片| 久久视频一区二区| 国产精品xxxav免费视频| 欧美成人激情视频免费观看| 国产精品免费一区二区三区在线观看| 欧美国产视频在线| 国产欧美一区二区在线观看| 最新成人av在线| 黑人中文字幕一区二区三区| 一区二区三区 在线观看视频| 一区二区三区在线视频观看| 在线视频欧美精品| 亚洲精品美女在线观看| 久久福利毛片| 欧美一区二区三区婷婷月色| 欧美久久成人| 99在线热播精品免费| 久久久亚洲人| 久久精品国亚洲| 国产精品一区毛片| 99综合视频| 99在线精品视频在线观看| 欧美顶级艳妇交换群宴| 每日更新成人在线视频| 国产亚洲一区二区精品| 亚洲一区三区在线观看| 国产精品青草久久| 亚洲一区二区三| 亚洲综合精品| 国产精品高潮呻吟视频| 在线综合欧美| 亚洲一区二区欧美| 欧美视频日韩视频在线观看| 亚洲人成网站在线播| 欧美日韩和欧美的一区二区| 免费中文日韩| 欧美一级大片在线免费观看| 欧美大秀在线观看| 欧美精品观看| 欧美福利网址| 国产精品日韩一区二区| 欧美日韩在线播放| 国产欧美日本一区二区三区| 国外成人在线视频| 日韩视频中文字幕| 免费看成人av| 久久精品中文| 9l视频自拍蝌蚪9l视频成人| 亚洲欧美国内爽妇网| 美女视频黄a大片欧美| 午夜精品一区二区三区电影天堂| 欧美劲爆第一页| 亚洲人成人99网站| 欧美成人精品h版在线观看| 欧美一区二区三区播放老司机| 亚洲黄色一区二区三区| 一区二区日韩免费看| 亚洲国产成人久久| 久久久久久91香蕉国产| 国产精品夜色7777狼人| 欧美一区二区三区在线观看| 亚洲一线二线三线久久久| 国产午夜精品美女视频明星a级 | 夜夜精品视频一区二区| 久久人人九九| 国产精品乱人伦一区二区| 亚洲人成人99网站| 亚洲美女毛片| 国产精品国产自产拍高清av| 亚洲一区二区三区涩| 久久不射电影网| 久久av老司机精品网站导航| 亚洲欧美另类在线| 猛干欧美女孩| 99视频日韩| 亚洲盗摄视频| 亚洲一区二区三| 最新日韩中文字幕| 欧美精品久久久久a| 亚洲欧美激情四射在线日 | 亚洲精品一区二| 欧美激情精品久久久六区热门| 在线一区亚洲| 亚洲尤物视频网| 亚洲国产成人午夜在线一区| 亚洲少妇诱惑| 亚洲深夜影院| 国产精品成人一区二区艾草| 亚洲人妖在线| 一区二区日韩免费看| 久久国产精品99精品国产| 最近看过的日韩成人|