【C++入门到精通】 原子性操作库(atomic) C++11 [ C++入门 ]

阅读导航

引言

当谈及并发编程时,确保数据的安全性和一致性是至关重要的。在C++11中引入的原子性操作库(atomic)为我们提供了一种有效且可靠的方式来处理多线程环境下的数据共享与同步问题。原子操作是不可分割的操作,它们可以确保在多线程环境中对共享数据的读写操作是原子的,即不会被其他线程中断或干扰。

本文将继续为大家介绍C++11中的一些重要特性,包括原子性操作库(atomic),这些特性能够帮助我们更好地管理多线程程序,提高程序的性能和稳定性。

一、原子性操作库简介

原子性操作库(atomic)是C++11中新增的标准库,它提供了一种线程安全的方式来访问和修改共享变量,避免了数据竞争的问题。在多线程程序中,如果多个线程同时对同一个变量进行读写操作,就可能会导致数据不一致的问题。原子性操作库通过使用原子操作来保证多个线程同时访问同一个变量时的正确性。

原子性操作库的官方文档

⭕在原子性操作库中,每个原子变量都有以下几个特点:

  1. 原子变量的读写操作是原子的,即不会被其他线程中断。
  2. 原子变量的值可以被多个线程同时访问和修改。
  3. 原子变量的修改操作是按照一定顺序进行的,保证了多个线程对同一个变量进行操作时的正确性。

原子性操作库中提供了一系列的原子操作函数,包括load、store、exchange、compare_exchange等。load函数用于读取原子变量的值,store函数用于设置原子变量的值,exchange函数用于交换原子变量的值,而compare_exchange函数用于比较并交换原子变量的值。后面我会详细介绍

二、原子变量

原子性操作库(atomic)提供了多种类型的原子变量,包括boolcharshortintlonglong long等基本数据类型,以及intmax_tuintmax_tintptr_t等扩展类型。每个原子变量都有对应的原子类型,比如atomic_boolatomic_charatomic_int等。在使用时,我们需要根据实际的需求选择合适的原子类型和原子变量。

1. 原子类型

下面是原子性操作库中支持的一些原子类型:

原子类型 描述
atomic_bool 原子布尔型,只能存储true或false。
atomic_char 原子字符型,相当于char类型。
atomic_uchar 原子无符号字符型,相当于unsigned char类型。
atomic_schar 原子有符号字符型,相当于signed char类型。
atomic_short 原子短整型,相当于short类型。
atomic_ushort 原子无符号短整型,相当于unsigned short类型。
atomic_int 原子整型,相当于int类型。
atomic_uint 原子无符号整型,相当于unsigned int类型。
atomic_long 原子长整型,相当于long类型。
atomic_ulong 原子无符号长整型,相当于unsigned long类型。
atomic_llong 原子长长整型,相当于long long类型。
atomic_ullong 原子无符号长长整型,相当于unsigned long long类型。
atomic_wchar_t 原子宽字符型,相当于wchar_t类型。
atomic_char16_t 原子16位字符型,相当于char16_t类型。
atomic_char32_t 原子32位字符型,相当于char32_t类型。
atomic_intmax_t 原子最大宽度整数类型,对应<inttypes.h>中的intmax_t类型。
atomic_uintmax_t 原子最大宽度无符号整数类型,对应<inttypes.h>中的uintmax_t类型。
atomic_intptr_t 原子指针宽度整数类型,对应<stddef.h>中的intptr_t类型。
atomic_uintptr_t 原子指针宽度无符号整数类型,对应<stddef.h>中的uintptr_t类型。
atomic_size_t 原子size_t类型,用于表示对象的大小。
atomic_ptrdiff_t 原子ptrdiff_t类型,用于表示两个指针之间的距离。

2. 原子类型函数

🚨注意原子类型和原子操作函数需要包含 <atomic> 头文件才能使用

下面是常用的原子类型函数:

函数 描述
load() 原子读取操作,用于获取原子变量的当前值。
store() 原子写入操作,用于设置原子变量的值。
exchange() 原子交换操作,用于交换原子变量的值,并返回原始值。
fetch_add() 原子加法操作,用于增加原子变量的值,并返回原始值。
fetch_sub() 原子减法操作,用于减少原子变量的值,并返回原始值。
fetch_and() 原子按位与操作,用于按位与原子变量的值,并返回原始值。
fetch_or() 原子按位或操作,用于按位或原子变量的值,并返回原始值。
fetch_xor() 原子按位异或操作,用于按位异或原子变量的值,并返回原始值。
fetch_min() 原子最小值操作,将原子变量与给定值比较,并将较小的值存储在原子变量中。返回原始值。
fetch_max() 原子最大值操作,将原子变量与给定值比较,并将较大的值存储在原子变量中。返回原始值。
fetch_mul() 原子乘法操作,将原子变量与给定值相乘,并将结果存储在原子变量中。返回原始值。
fetch_div() 原子除法操作,将原子变量与给定值相除,并将结果存储在原子变量中。返回原始值。
fetch_and_not() 原子按位与非操作,对原子变量进行按位与非运算,并将结果存储在原子变量中。返回原始值。
fetch_negate() 原子取反操作,对原子变量进行取反运算,并将结果存储在原子变量中。返回原始值。
fetch_bitwise_and() 原子按位与操作,将原子变量与给定值进行按位与运算,并将结果存储在原子变量中。返回原始值。
fetch_bitwise_or() 原子按位或操作,将原子变量与给定值进行按位或运算,并将结果存储在原子变量中。返回原始值。
fetch_bitwise_xor() 原子按位异或操作,将原子变量与给定值进行按位异或运算,并将结果存储在原子变量中。返回原始值。

🚨注意以上函数只是原子类型库中的一部分函数,还有其他函数可用于更复杂的操作,具体取决于你的需求。

3. 使用示例

下面是一个使用原子性操作库的样例,展示了如何创建和操作原子变量:

cpp 复制代码
#include <atomic>
#include <iostream>

int main() {
    std::atomic_int counter(0); // 创建一个原子整型变量并初始化为0

    counter++; // 原子操作:递增counter的值

    int value = counter.load(); // 原子操作:读取counter的值
    std::cout << "Counter value: " << value << std::endl;

    counter.store(10); // 原子操作:将counter的值设置为10

    bool exchanged = counter.compare_exchange_weak(value, 5); // 原子操作:比较并交换counter的值
    if (exchanged) {
        std::cout << "Value exchanged successfully!" << std::endl;
    } else {
        std::cout << "Value exchange failed!" << std::endl;
    }

    return 0;
}

在这个样例中,我们首先使用std::atomic_int创建一个原子整型变量counter并将其初始化为0。然后,我们演示了几种原子操作:

  • counter++:原子递增操作,使用++操作符自增counter的值。
  • counter.load():原子读取操作,读取counter的当前值。
  • counter.store(10):原子写入操作,将counter的值设置为10。
  • counter.compare_exchange_weak(value, 5):原子比较并交换操作,比较counter的值与value是否相等,如果相等则将counter的值设为5,并返回交换是否成功的结果。

以上是原子性操作库的简单使用样例,通过使用原子类型和原子操作,我们可以确保多线程环境下对共享变量的安全访问和修改

三、总结

通过学习本文所介绍的内容,我们可以更好地理解并发编程中的原子性操作库的概念和作用。原子操作库提供了一种可靠、高效的方式来处理多线程环境下的数据共享和同步问题。在实际应用中,我们需要根据具体场景选择适当的原子类型和操作函数,并合理设置内存顺序,以平衡性能和正确性需求。

综上所述,原子性操作库是C++11中一个强大而重要的工具,它为我们在多线程编程中处理数据共享与同步提供了有效的解决方案。通过合理运用原子类型和操作函数,我们能够编写出更加健壮和可靠的多线程应用程序。希望本文对读者在学习并发编程中的原子性操作库有所帮助。

温馨提示

感谢您对博主文章的关注与支持!另外,我计划在未来的更新中持续探讨与本文相关的内容,会为您带来更多关于C++以及编程技术问题的深入解析、应用案例和趣味玩法等。请继续关注博主的更新,不要错过任何精彩内容!

再次感谢您的支持和关注。期待与您建立更紧密的互动,共同探索C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!

相关推荐
轩辰~8 分钟前
网络协议入门
linux·服务器·开发语言·网络·arm开发·c++·网络协议
智慧老师26 分钟前
Spring基础分析13-Spring Security框架
java·后端·spring
lxyzcm28 分钟前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
蜀黍@猿1 小时前
C/C++基础错题归纳
c++
V+zmm101341 小时前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
雨中rain1 小时前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13141 小时前
常用的缓存技术都有哪些
java
AiFlutter2 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
ALISHENGYA2 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法