template< class T >
struct atomic;
std::atomic::atomic
std::atomic<bool> ready (false);
std::atomic<int> a;
is_lock_free函数是一个成员函数,用于检查当前atomic对象是否支持无锁操作。调用此成员函数不会启动任何数据竞争
bool is_lock_free() const volatile noexcept;
bool is_lock_free() const noexcept;
std::atomic_flag是 C++ 中的一个原子布尔类型,它用于实现原子锁操作。
//原子锁
class CASLock : Noncopyable {
public:
typedef ScopedLockImpl<CASLock> Lock;
CASLock(){
m_mutex.clear();
}
~CASLock(){
}
void lock(){
while(std::atomic_flag_test_and_set_explicit(&m_mutex , std::memory_order_acquire));
}
void unlick(){
std::atomic_flag_clear_explicit(&m_mutex , std::memory_order_release);
}
private:
// 原子状态
volatile std::atomic_flag m_mutex;
};
atomic_flag lock = ATOMIC_FLAG_INIT;// 设置为false状态
void f(int n){
// test_and_set会不断设置新值并返回旧值
while (lock.test_and_set(std::memory_order_acquire))
cout << "Waiting from thread " << n << endl;
cout << "Thread" << n << " starts working" << endl;
}
void g(int n) {
cout << "Thread " << n << " is going to start" << endl;
lock.clear();// 将lock设置false
cout << "Thread " << n << " starts working" << endl;
}
void test() {
lock.test_and_set();
thread t1(f, 1);
thread t2(g, 2);
t1.join();
sleep(5);
t2.join();
}
// 当t1执行后,lock为true,则一直自旋等待,直到t2加入后,clear将其设置为false,t1才终止自旋,执行后续代码;
void store(T desired, std::memory_order order = std::memory_order_seq_cst) volatile noexcept;
void store(T desired, std::memory_order order = std::memory_order_seq_cst) noexcept;
desired:要存储的值。
order:存储操作的内存顺序。默认是std::memory_order_seq_cst
#include
#include
int main()
{
std::atomic<int> atomic_int(0);
int val = 10;
atomic_int.store(val);
std::cout << "Value stored in atomic object: " << atomic_int << std::endl;
return 0;
}
//Value stored in atomic object: 10
【硬件内存模型】
当执行按照一定的顺序执行,则该内存模型为强顺序;
当执行不一定按照顺序执行,则该模型为弱顺序;
在多线程中,当线程间的内存数据被改变的顺序与机器指令中声明的不一致,则为弱顺序;
而上述的原子操作时强顺序的;
- 弱顺序的指令执行性能一般较高,当没有要求需要顺序执行时,使用该方式可以给程序提高性能;
【C++内存模型】
- 编译器保证原子操作间的指令顺序不变;
- 处理器对原子操作的汇编指令的执行顺序不变;
部分平台会阻止编译器优化,加入内存栅栏来保证atomic的顺序一致性,将会大大影响性能;
【如何解决不阻止编译器优化】:让程序为原子操作指定内存顺序(memory_order);
能够让编译器重排序或处理器乱序执行;
memory_order_relaxed :不对执行顺序做任何保证;
memory_order_acquire :本线程中,所有后续的读操作必须再本条原子操作完成后执行;
memory_order_release :本线程中,所有之前的写操作完成后才能执行本条原子操作;
memory_order_acq_rel :同时包含memory_order_acquire、memory_order_release;
memory_order_consume :本线程中,所有后续的有关原子类型操作,后再本条原子操作完成后执行;
memory_order_seq_cst :全部存取都按顺序执行(可能会导致性能损失);
- 上述中,可以使用memory_order_release和memory_order_consume产生;
load函数用于获取原子变量的当前值。
T load(memory_order order = memory_order_seq_cst) const noexcept;
operator T() const noexcept;
load函数的参数memory_order表示内存序,也就是对原子变量的读操作要遵循哪种内存模型。C++中定义了多种内存序,包括:
使用load函数时,如果不指定memory_order,则默认为memory_order_seq_cst。
std::atomic<int> foo (0);
int x;
do {
x = foo.load(std::memory_order_relaxed); // get value atomically
} while (x==0);
访问和修改包含的值,将包含的值替换并返回它前面的值。
template< class T >
T exchange( volatile std::atomic<T>* obj, T desired );
// atomic::load/store example
#include // std::cout
#include // std::atomic, std::memory_order_relaxed
#include // std::thread
//std::atomic count = 0;//错误初始化
std::atomic<int> count(0); // 准确初始化
void set_count(int x)
{
std::cout << "set_count:" << x << std::endl;
count.store(x, std::memory_order_relaxed); // set value atomically
}
void print_count()
{
int x;
do {
x = count.load(std::memory_order_relaxed); // get value atomically
} while (x==0);
std::cout << "count: " << x << '\n';
}
int main ()
{
std::thread t1 (print_count);
std::thread t2 (set_count, 10);
t1.join();
t2.join();
std::cout << "main finish\n";
return 0;
}