合肥做网站行吗,公司管理,今天重大新闻文字,软件库合集软件资料2024std::atomic 文章目录 std::atomic构造函数is_lock_free函数std::atomic_flagatomic_flag实现原子锁atomic_flag实现自旋锁 store函数内存模型load函数exchange函数示例 C中原子变量#xff08;atomic#xff09;是一种多线程编程中常用的同步机制#xff0c;它能够确保对共…std::atomic 文章目录 std::atomic构造函数is_lock_free函数std::atomic_flagatomic_flag实现原子锁atomic_flag实现自旋锁 store函数内存模型load函数exchange函数示例  C中原子变量atomic是一种多线程编程中常用的同步机制它能够确保对共享变量的操作在执行时不会被其他线程的操作干扰从而避免竞态条件race condition和死锁deadlock等问题。 C11起提供了atomic可以使用它定义一个原子类型。 template class T 
struct atomic;构造函数 
std::atomic::atomic 
std::atomicbool ready (false);
std::atomicint a;is_lock_free函数 
is_lock_free函数是一个成员函数用于检查当前atomic对象是否支持无锁操作。调用此成员函数不会启动任何数据竞争 
bool is_lock_free() const volatile noexcept;
bool is_lock_free() const noexcept;std::atomic_flag 
std::atomic_flag是 C 中的一个原子布尔类型它用于实现原子锁操作。 
std::atomic_flag 默认是清除状态false。可以使用 ATOMIC_FLAG_INIT 宏进行初始化例如std::atomic_flag flag  ATOMIC_FLAG_INIT;std::atomic_flag 提供了两个成员函数 test_and_set() 和 clear() 来测试和设置标志位。test_and_set() 函数会将标志位置为 true并返回之前的值clear() 函数将标志位置为 false。std::atomic_flag 的 test_and_set() 和 clear() 操作是原子的可以保证在多线程环境下正确执行。std::atomic_flag 只能表示两种状态即 true 或 false不能做其他比较操作。通常情况下std::atomic_flag 被用作简单的互斥锁而不是用来存储信息。 
atomic_flag实现原子锁 
//原子锁
class CASLock : Noncopyable {
public:typedef ScopedLockImplCASLock 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实现自旋锁 
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设置falsecout  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将其设置为falset1才终止自旋执行后续代码store函数 
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 iostream
#include atomicint main()
{std::atomicint 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函数 
load函数用于获取原子变量的当前值。 
T load(memory_order order  memory_order_seq_cst) const noexcept;
operator T() const noexcept;load函数的参数memory_order表示内存序也就是对原子变量的读操作要遵循哪种内存模型。C中定义了多种内存序包括 
memory_order_relaxed最轻量级的内存序不提供任何同步机制。memory_order_acquire在本线程中所有后面的读写操作必须在这个操作之后执行。memory_order_release在本线程中该操作之前的所有读写操作必须在这个操作之前执行。memory_order_seq_cst最严格的内存序保证所有线程看到的读写操作的顺序都是一致的。 使用load函数时如果不指定memory_order则默认为memory_order_seq_cst。 std::atomicint foo (0);int x;
do {x  foo.load(std::memory_order_relaxed);  // get value atomically
} while (x0);exchange函数 
访问和修改包含的值将包含的值替换并返回它前面的值。 
template class T 
T exchange( volatile std::atomicT* obj, T desired );示例 
// atomic::load/store example
#include iostream // std::cout
#include atomic // std::atomic, std::memory_order_relaxed
#include thread // std::thread
//std::atomicint count  0;//错误初始化
std::atomicint 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 (x0);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;
}