C++11中引入了原子变量模板类型,原子变量的引入,极大的方便了开发者开发多并发程序。工作中也经常使用原子变量,今天针对具体类型std::atomic
std::atomic
(1) -- ++操作
(2)store(写操作)
(3)load(读操作)
(4)exchange(交换数据)
(5)compare_exchange_weak (CAS)
(6)compare_exchange_strong (加强版的CAS,性能略差)
说明:
compare_exchange_weak和compare_exchange_strong都是比较并更新操作,功能类似,compare_exchange_weak允许偶然出乎意料的返回false,在原始值和比较值一致时,通常比compare_exchange_strong有更高的性能。函数会传入比较值和更新值,进行如下操作:
1)如果原始值与比较值一致,则将原始值修改为更新值,并返回true
2)如果原始值与比较值不一致,则将比较值修改为原始值,并返回false
1.简单累加操作
在多线程中通常需要统计某个操作调用了多少次,此时可以利用原子变量统计比加锁更加高效和快捷,举例如下:
- #include
- #include
-
- static std::atomic<unsigned long long> s_sequence_index(0);
-
- void no_lock_statistics() {
- std::thread th1([&]{
- for (int i = 0; i < 1000000; i++) {
- ++s_sequence_index;
- }
- });
- std::thread th2([&]{
- for (int i = 0; i < 1000000; i++) {
- ++s_sequence_index;
- }
- });
- std::thread th3([&]{
- for (int i = 0; i < 1000000; i++) {
- ++s_sequence_index;
- }
- });
- std::thread th4([&]{
- for (int i = 0; i < 1000000; i++) {
- ++s_sequence_index;
- }
- });
- th1.join();
- th2.join();
- th3.join();
- th4.join();
- std::cout << "statistics:: " << s_sequence_index.load() << std::endl;
- }
-
- int main() {
- no_lock_statistics();
- return 0;
- }
运行结果如下:
![]()
通过运行看,4个线程同时对一个原子变量操作1000000次++,操作结束原子变量变为4000000,如果s_sequence_index改为普通的类型,操作结束结果不会变为4000000。
2.获取并更新值操作
在实际多线程开发中,往往需要比较,获取和更新某个变量,这一系列操作想要保证原子操作,如果没有原子变量,往往需要增加互斥锁。有了原子变量之后,操作就会变得很容易
- #include
- #include
-
- static std::atomic<unsigned long long> s_sequence_index(0);
-
- uint64_t get_index() {
- unsigned long long _index = 0;
- do {
- _index = s_sequence_index;
- } while(!s_sequence_index.compare_exchange_weak(_index, _index + 1));
- return (uint64_t)_index;
- }
-
- void test_get_index() {
- for (int i = 0; i < 100; i++) {
- std::thread([&]{
- std::cout << get_index() << std::endl;
- }).detach();
- }
- getchar();
- std::cout << "end:: " << s_sequence_index << std::endl;
- }
-
- int main() {
- test_get_index();
- return 0;
- }
运行结果如下:

如上图示,多线程不重复的获取原子变量的值,并对其进行更新,保证原子变量值的连续性和排他性。
自定义类型原子变量std::atomic
(1)store(写操作)
(2)load(读操作)
(3)exchange(交换数据)
(4)compare_exchange_weak (CAS)
(5)compare_exchange_strong
如下将展示使用原子操作多线程操作链表的例子
- #include
- #include
-
- template<typename T>
- class LockFreeList
- {
- private:
- struct Node
- {
- T _data;
- Node* _next;
-
- Node(T const& data): _data(data), _next(nullptr) {
- }
- };
-
- public:
- LockFreeList() : _head(nullptr) {
- }
-
- void push(T const& data) {
- Node* new_node = new Node(data);
- new_node->_next = _head.load();
- while (!_head.compare_exchange_weak(new_node->_next, new_node));
- }
-
- void show() {
- Node* tmpNode = _head;
- while(tmpNode) {
- std::cout << tmpNode->_data << " ";
- tmpNode = tmpNode->_next;
- }
- std::cout << std::endl;
- }
-
- private:
- std::atomic
_head; - };
-
- static LockFreeList<int> _s_lock_free_list;
- static std::atomic<int> _s_free_int(0);
-
- void test_lock_free_list() {
- for (int i = 0; i < 1000; i++) {
- std::thread([&](){
- _s_lock_free_list.push(_s_free_int++);
- }).detach();
- }
- getchar();
- _s_lock_free_list.show();
- }
-
- int main() {
- test_lock_free_list();
- return 0;
- }
运行结果如下:

通过测试以看到,数据被无重复的插入到了链表之中。