详解c++ atomic原子编程中的Memory Order

yizhihongxing

当使用C++中的原子类型进行编程时,需要指定原子操作的内存顺序(Memory Order),以保证多线程下的正确性和一致性。

C++中原子操作的内存顺序一共有4种:

  1. memory_order_relaxed:最轻松的内存顺序,不会保证原子操作的顺序,也不保证操作的内存可见性。当我们要进行仅仅是读写共享内存而无需考虑同步问题的操作时,可以使用memory_order_relaxed。

示例1:使用relaxed内存顺序进行无锁统计

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

int main() {
    std::atomic<int> counter(0);
    std::thread thread1([&counter]() {
       for (int i = 0; i < 100000; i++) {
           counter.fetch_add(1, std::memory_order_relaxed);
       }
    });

    std::thread thread2([&counter]() {
        for (int i = 0; i < 100000; i++) {
            counter.fetch_add(1, std::memory_order_relaxed);
        }
    });

    thread1.join();
    thread2.join();
    std::cout << counter << std::endl;
    return 0;
}

在这个示例中,我们使用了memory_order_relaxed内存顺序进行了两次原子操作,每次都是将counter原子变量加1。由于C++标准未规定内存操作的执行顺序以及内存可见性,所以在不同的平台和不同的编译器下,结果可能不同。但是在本示例中,多线程下的结果符合预期。

  1. memory_order_acquire:当一个线程使用memory_order_acquire方式读取一个原子变量时,它自己的所有后续操作都不能在此之前执行,以此保证前面的读取的值是最新的。

示例2:使用acquire-read和release-write解决多线程下的生产消费模型

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

using namespace std;

vector<int> pool;
atomic<int> pool_index(0);

void producer() {
    for (int i = 0; i < 100000; i++) {
        int index = pool_index.fetch_add(1, std::memory_order_relaxed);
        pool[index] = i;
        // 发布对第index个元素的写操作
        atomic_thread_fence(std::memory_order_release);
    }
}

void consumer() {
    while (true) {
        int index = pool_index.fetch_sub(1, std::memory_order_acquire);
        // 加载第index个元素的值
        atomic_thread_fence(std::memory_order_acquire);
        if (index <= 0) {
            // 如果生产者已经停止了,则退出消费线程
            break;
        }
        cout << "consume: " << pool[index - 1] << endl;
    }
}

int main() {
    pool.resize(100000);
    thread t1(producer);
    thread t2(consumer);
    thread t3(consumer);
    t1.join();
    pool_index.store(0); // 停止生产者
    t2.join();
    t3.join();
    return 0;
}

在本示例中,我们通过使用acquire读和release写操作,避免了内存可见性和顺序的问题,从而实现了多个生产者和多个消费者协同工作的生产消费模型。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解c++ atomic原子编程中的Memory Order - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • JSON传递bool类型数据的处理方式介绍

    JSON(JavaScript Object Notation)是一种用于数据交换的轻量级文本格式,被广泛应用于前后端通信中。在JSON中,bool类型数据表示为true或false。在传递bool类型数据时,我们需要明确如何对其进行处理。 在PHP中,我们需要使用json_encode()函数将bool类型数据转换为JSON字符串,使用json_decod…

    C 2023年5月23日
    00
  • php时间函数用法分析

    PHP时间函数用法分析 1. 介绍 在 PHP 编程中,经常需要获取、操作时间。PHP 提供了一系列的时间函数,可以方便地处理日期、时间相关的操作。本文将分析 PHP 时间函数的常见用法,包括获取时间戳、格式化时间、时间计算等。 2. 时间戳 时间戳是指从“格林尼治标准时间 1970 年 1 月 1 日 0 点 0 分 0 秒”到现在所经过的秒数。在 PHP…

    C 2023年5月22日
    00
  • 详解C语言之顺序表

    详解C语言之顺序表 什么是顺序表? 顺序表是一种数据结构,它是由一块连续的存储空间表示的线性表,可以通过下标直接寻址访问表中元素。顺序表的插入和删除操作比较困难,但是查找操作比较容易。它是一种静态的数据结构,不能动态改变其大小。 实现顺序表的基本结构 在C语言中,我们可以用数组来实现顺序表的基本结构,如下所示: #define MAXSIZE 100 // …

    C 2023年5月24日
    00
  • 如何在 C++ 中实现一个单例类模板

    当我们在开发一个项目时,有时需要一个只能被实例化一次的类,这种情况下就需要使用单例模式。C++中实现单例模式可以通过单例类模板来实现。 下面详细讲解如何在C++中实现一个单例类模板: 1. 定义单例类 template<typename T> class Singleton { public: static T& instance() {…

    C 2023年5月23日
    00
  • 关于在C程序中处理UTF-8文本的方法详解

    关于在C程序中处理UTF-8文本的方法详解 在处理UTF-8编码的文本时,我们需要使用一些特殊的方法,而不能像处理ASCII编码的文本那样简单。以下是在C程序中处理UTF-8文本的方法详解: 1. 了解UTF-8编码 要处理UTF-8编码的文本,首先需要了解UTF-8编码的原理。UTF-8是一种变长字符编码,每个字符的长度都不一定相同。在UTF-8编码中,如…

    C 2023年5月23日
    00
  • C/C++高精度(加减乘除)算法的实现

    C/C++高精度算法实现方法 背景 C/C++内置的整型数据类型(int、long等)的取值范围都有限制,例如int类型的取值范围为-2147483648~2147483647,这个取值范围对于绝大部分的算法应用是足够的。但是有时候我们需要进行很大数的计算,此时常规的整型数据类型就无能为力了。这时我们需要实现高精度算法来解决这个问题。 实现 高精度算法的实现…

    C 2023年5月23日
    00
  • 你不知道的C++中namespace和using的用法实例

    下面将详细讲解关于C++中namespace和using的用法实例,内容包含两条示例说明。 1. namespace的用法实例 1.1 什么是namespace? 在C++中,命名空间(namespace)是一个用于区分不同部分代码的机制。当编写代码时,我们可能会使用许多标识符,例如变量名、函数名等。如果所有标识符都放在同一命名空间内,可能会出现重名的情况,…

    C 2023年5月23日
    00
  • C/C++ 编译器优化介绍

    C/C++ 编译器优化介绍 C/C++ 编译器通过优化可以让代码运行更快、更高效,提升程序的性能和响应速度。本文将介绍常用的 C/C++ 编译器优化技术,以及对应的编译器选项和示例说明。 基本编译器优化 优化等级 编译器一般提供多个不同的优化等级,包括 “-O0” 到 “-O3″ 等级。其中,”-O0″ 表示不进行任何优化,而 “-O3” 表示最高级别的优化…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部