原子操作 |
原子操作是一类不可分割的操作,当操作在任意线程中进行一半时,是不能被查看;它的状态要么是完成,要么是未完成。如果从对象中读取一个值的操作是原子的,并且对对象的所有修改也都是原子的话,那么加载操作要么会检索到对象初始化值,要么就将值存在某一次修改中。非原子操作可能会被视为由一个线程完成一半的操作。如果是一个存储操作,那么其他线程看到的,可能既不是存储前的值,也可能不是已存储的值;如果非原子操作是一个加载操作,那么它可能会去检索对象的部分成员,或是在另一个线程修改了对象的 值后,对对象进行检索;所以,检索出来的值可能既不是第一个值,也不是第二个值,可能是某种两者结合的值,会构成数据竞争,且会伴有有未定义行为。 |
原子类型/相关特化类 |
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); } }; |