atomic使用
概述
本文只要讲述C++11中atomic的使用,并通过示例来进一步的说明。
介绍
atomic在c++11中被引入,作为一种原子操作,之所以是原子操作,是因为其能保证操作过程不会被打断或终止,保证了被操作数据的安全性。原子操作是线程安全的。尤其在多线程同步中,常用于基本类型共享数据的保护。
原子操作:指的是不可被中断的一个或一系列操作,这些操作要么全部执行成功,要么全部不执行。
使用场景
-
并发计数器:在多线程环境下,如果多个线程对同一个变量进行自增操作,可能会导致数据不一致。使用atomic可以确保自增操作的原子性,从而确保计数的准确性。
-
读取和修改共享变量:当多个线程同时读取和修改同一个共享变量时,如果不使用原子操作,可能会导致数据冲突。使用atomic可以确保读取和修改操作的原子性,避免数据不一致。
-
信号量:在多线程编程中,信号量常用于线程间的同步和通信。使用atomic可以确保对信号量的操作是原子的,从而避免出现竞态条件。
头文件
使用时需要头文件:
#include<atomic>
atomic的使用
创建
atomic是一个模板类型,可以用于基本数据类型的原子操作。非基本数据类型需要重新去实现一系列的复杂操作,不建议这样做。
以创建int型变量为例:
atomic<int> nAtomic;
此时nAtomic里的值为默认值0。
load()
实际上就是取出nAtomic的值:
nAtomic.load();//0
store()
向nAtomic变量中存储一个数值:
nAtomic.store(3);
exchange()
以原子方式交换变量的值,并返回旧值。
int nOld = nAtomic.exchange(5);
compare_exchange_weak
用于比较和交换两个数值。当nAtomic的当前值与期望值相等,更新为新值,否则,保持nAtomic中的值不变。
int expired = 23;
int newValue = 6;
if (nAtomic.compare_exchange_weak(expired, newValue)) {
//true当前值与期望值相等,设置为新值
cout << "当前值与期望值相等,更新新值成功,g_countAtomic = " << nAtomic<< endl;
}
else {
//当前值与期望值不想等,还是原来的值
cout << "当前值与期望值不相等,没有更新新值,g_countAtomic = " << nAtomic<< endl;
}
compare_exchange_strong()
与compare_exchange_weak()功能一样。区别是:
-
阻塞:如果比较和交换操作失败,函数通常会忙等待(busy-wait)直到条件满足为止。这意味着它会持续检查条件,直到可以安全地执行比较和交换为止。这种忙等待行为可能会导致 CPU 资源的浪费,因此在高并发场景中可能需要谨慎使用。
-
一致性保证:与 compare_exchange_weak() 相比,compare_exchange_strong() 提供更强的内存一致性保证。具体来说,它确保了在比较和交换操作成功执行后,其他线程将立即看到更新后的值。这是通过强制使用特定的内存排序规则来实现的,这些规则确保了在多线程环境中的可见性和顺序性。
当多线程环境下,一般使用compare_exchange_weak()在一个循环中,确保没有被虚假的比较和交换失