首页 > 编程语言 >C++ 原子变量atomic variable

C++ 原子变量atomic variable

时间:2024-09-05 12:21:58浏览次数:11  
标签:std 顺序 int C++ 原子 atomic memory variable

原子变量

原子变量(atomic variable)是 C++11 引入的一种同步机制,用于在多线程环境中进行无锁的、线程安全的操作。原子变量的操作是不可分割的,即在执行过程中不会被其他线程中断,从而避免了数据竞争和不一致的问题。原子变量位于 头文件中。

基本概念

原子性

原子性:一个操作是原子的,意味着它在执行过程中不会被其他线程中断。原子操作要么完全执行,要么完全不执行,不存在部分执行的状态。

数据竞争

数据竞争:当多个线程同时访问同一个内存位置,并且至少有一个线程在写入数据时,就会发生数据竞争。数据竞争可能导致未定义行为和数据不一致。

原子变量的类型

C++ 标准库提供了多种原子类型,包括:

std::atomic:模板类,可以用于任何可复制的类型 T。

特化类型:如 std::atomic_bool、std::atomic_int、std::atomic_uint 等。

基本用法

定义原子变量:

#include <atomic>

std::atomic<int> atomic_int;
std::atomic_bool atomic_bool;

原子操作

原子变量支持多种原子操作,包括:

加载(load):读取原子变量的值。

存储(store):写入原子变量的值。

交换(exchange):将原子变量的值替换为新值,并返回旧值。

比较交换(compare-exchange):如果原子变量的值等于预期值,则将其替换为新值,并返回操作是否成功。

#include <atomic>
#include <iostream>

int main() {
    std::atomic<int> atomic_int(0);

    // 加载操作
    int value = atomic_int.load();
    std::cout << "Loaded value: " << value << std::endl;

    // 存储操作
    atomic_int.store(42);
    std::cout << "Stored value: " << atomic_int.load() << std::endl;

    // 交换操作
    int old_value = atomic_int.exchange(99);
    std::cout << "Exchanged value: " << old_value << ", new value: " << atomic_int.load() << std::endl;

    // 比较交换操作
    int expected = 99;
    bool success = atomic_int.compare_exchange_strong(expected, 100);
    std::cout << "Compare-exchange result: " << success << ", expected: " << expected << ", new value: " << atomic_int.load() << std::endl;

    return 0;
}

内存顺序

原子操作可以指定内存顺序(memory order),用于控制内存访问的顺序和可见性。C++ 提供了多种内存顺序选项,包括:

  1. std::memory_order_relaxed
    特点:最宽松的内存顺序,不保证顺序和可见性。
    用途:适用于不需要顺序保证的场景,如简单的计数器。
  2. std::memory_order_consume
    特点:保证依赖关系的顺序。
    用途:适用于依赖关系的数据依赖场景。
  3. std::memory_order_acquire
    特点:保证读取操作的顺序。
    用途:适用于读取操作需要顺序保证的场景。
  4. std::memory_order_release
    特点:保证写入操作的顺序。
    用途:适用于写入操作需要顺序保证的场景。
  5. std::memory_order_acq_rel
    特点:同时保证读取和写入操作的顺序。
    用途:适用于读取和写入操作都需要顺序保证的场景。
  6. std::memory_order_seq_cst
    特点:最严格的内存顺序,保证所有线程看到的操作顺序一致。
    用途:适用于需要最强顺序保证的场景。
#include <atomic>
#include <iostream>

int main() {
    std::atomic<int> atomic_int(0);

    // 使用 memory_order_seq_cst 进行存储操作
    atomic_int.store(42, std::memory_order_seq_cst);

    // 使用 memory_order_seq_cst 进行加载操作
    int value = atomic_int.load(std::memory_order_seq_cst);
    std::cout << "Loaded value: " << value << std::endl;

    return 0;
}

示例代码

以下是一个完整的示例,展示了如何在多线程环境中使用原子变量进行线程安全的计数:

#include <atomic>
#include <iostream>
#include <thread>
#include <vector>

std::atomic<int> counter(0);

void increment_counter() {
    for (int i = 0; i < 1000; ++i) {
        counter.fetch_add(1, std::memory_order_relaxed);
    }
}

int main() {
    std::vector<std::thread> threads;

    // 创建多个线程进行计数
    for (int i = 0; i < 10; ++i) {
        threads.emplace_back(increment_counter);
    }

    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }

    // 输出最终计数结果
    std::cout << "Final counter value: " << counter.load() << std::endl;

    return 0;
}

Final counter value: 10000

总结

原子变量:用于在多线程环境中进行无锁的、线程安全的操作。

原子性:确保操作是不可分割的,避免数据竞争和不一致。

内存顺序:控制内存访问的顺序和可见性,提供多种选项以满足不同需求。

应用场景:适用于需要线程安全的计数器、标志位等场景。

标签:std,顺序,int,C++,原子,atomic,memory,variable
From: https://blog.csdn.net/gopher9511/article/details/141905953

相关文章

  • C++和Python混合编程——C++调用Python入门
    大纲代码结构初始化Python解释器获取GIL为什么需要GIL?GIL的影响导入Python模块并执行代码释放GIL终止Python解释器完整代码编译执行结果项目地址在《C++和Python混合编程——Python调用C++入门》一文中,我们熟悉了Python调用C++编译的动态库的方法。但是作......
  • C++11新特性
    C++11主要新特性有类的初始化与函数、新增关键字、std库新特性、lambda表达式、智能指针、线程1.关键字()nullptr取代NULL、0()constexpr:显式声明函数返回值、变量是一个常量表达式()auto:对变量类型推导,()decltype:对表达式类型推导,用法为decltype(表达式)()using:声明使用的命......
  • C++高精度乘法
    #include<iostream>#include<string>#include<cstring>usingnamespacestd;intmain(){stringstr1,str2;cin>>str1>>str2; //确定字符串长度 intlen1=str1.length(); intlen2=str2.length(); //确认积......
  • 编译原理项目——C++实现C语言编译器输出为gcc级汇编(代码/报告材料)
    完整的代码材料见文章末尾以下为核心内容和部分结果项目介绍function.cpp实现了共有的函数lexer.cpp词法分析器get_predict_table.cpp获取预测分析表LR.cpp语法分析generate.cpp语义分析中间代码生成to_asm.cpp目标代码生成部分核心代码LR分析#include"co......
  • 【C++】封装
    目录1.访问控制符2.封装的目的2.1.数据隐藏和保护2.2.接口与实现的分离2.3.控制访问3.封装的好处3.1.提高代码的安全性3.2.减少错误3.3.提高代码的可维护性3.4.增强代码的可读性3.5.促进模块化设计3.6.提高代码的可重用性3.7.支持面向对象的设计原则......
  • VScode「配置自动代码格式化C/C++」
    前言        你好,我是小莱,希望输出高质量的内容。        在大厂实习的过程中,我发现很多资深的开发者都习惯自己敲空格,按照公司的代码规范使用标尺来提示自己什么时候该换行。也许这样做可以增加代码编辑时的灵活性,但对于新入职场(用惯了VS)的小白来说,无疑大......
  • 《C++中的反射机制:开启高级编程之门》
    一、引言在现代编程中,反射机制是一种强大的工具,它允许程序在运行时检查和操作对象的结构和行为。虽然C++语言本身并没有内置的反射机制,但通过一些技巧和技术,我们可以在C++中实现类似的功能。本文将深入探讨如何在C++中实现反射机制,以及它在实际编程中的应用。二、什么......
  • 《C++中的移动构造函数与移动赋值运算符:高效编程的利器》
    一、引言在C++编程中,随着现代软件对性能要求的不断提高,高效地管理资源变得至关重要。C++11引入了移动语义,其中移动构造函数和移动赋值运算符成为了提高程序性能和资源管理效率的重要工具。本文将深入探讨C++中的移动构造函数和移动赋值运算符的作用,以及它们在实际编程中......
  • Win32 C++代码快速验证模板
    DLL模板#include<windows.h>#include<algorithm>#include<array>#include<cstdio>#include<cstdlib>#include<cstring>#include<deque>#include<iostream>#include<list>#include<map>#incl......
  • 6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)
    目录一.堆(Heap)的基本介绍二.堆的常用操作(以小根堆为例)三.实现代码3.1堆结构定义3.2向下调整算法*3.3初始化堆*3.4销毁堆3.4向上调整算法* 3.5插入数据3.6删除数据3.7返回堆顶数据四.下篇内容1.堆排序2.TopK问题一.堆(Heap)的基本介绍    ......