通知图标

欢迎访问津桥芝士站

atomic:std::atomic_fetch_and和std::atomic_fetch_and_explicit

来自AI助手的总结
本文探讨了C++中的原子操作函数std::atomic_fetch_and和std::atomic_fetch_and_explicit,确保多线程环境下数据的一致性与安全性。

引入

在多线程编程中,原子操作是一项至关重要的技术,用于维护不同线程之间共享数据的一致性和安全性。C++标准库中的<atomic>头文件提供了一些原子操作函数,其中std::atomic_fetch_andstd::atomic_fetch_and_explicit用于执行原子按位与(AND)操作。这些函数允许线程安全地对原子变量进行按位与操作,并返回操作之前的值,确保在多线程环境下不会发生数据竞争。本文将深入探讨这两个函数的特性、语法、完整示例代码以及适用场景分析。

特性/函数/功能语法介绍

std::atomic_fetch_and

std::atomic_fetch_and的主要特性包括:

  • 原子性:确保在执行按位与操作时不会被其他线程干扰。
  • 简便性:提供简单易用的接口,方便进行按位与操作。

语法

#include <atomic>

T std::atomic_fetch_and(std::atomic<T>& obj, T arg);

std::atomic_fetch_and_explicit

std::atomic_fetch_and_explicit的主要特性包括:

  • 内存序控制:允许指定内存序,从而增强程序的灵活性和控制力。
  • 适用于复杂场景:适合需要特定内存顺序的高性能应用。

语法

#include <atomic>

T std::atomic_fetch_and_explicit(std::atomic<T>& obj, T arg, std::memory_order order);

参数order可以是:

  • memory_order_relaxed:无顺序保证。
  • memory_order_acquire:在此调用之前的所有读取必须完成。
  • memory_order_release:在此调用之后的所有写入必须完成。
  • memory_order_acq_rel:同时保证读取和写入的顺序。
  • memory_order_seq_cst:确保全局顺序一致。

完整示例代码

以下示例展示了如何使用std::atomic_fetch_andstd::atomic_fetch_and_explicit来对共享变量进行原子按位与操作:

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

std::atomic<int> sharedValue{0xFF}; // 初始值为255 (0xFF)

void apply_mask(int mask) {
    for (int i = 0; i < 3; ++i) {
        int oldValue = std::atomic_fetch_and(sharedValue, mask); // 使用atomic_fetch_and
        std::cout << "Applied mask: " << mask 
                  << ", old value: " << oldValue 
                  << ", new value: " << (oldValue & mask) << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
}

void apply_mask_explicit(int mask) {
    for (int i = 0; i < 3; ++i) {
        int oldValue = std::atomic_fetch_and_explicit(sharedValue, mask, std::memory_order_seq_cst); // 使用atomic_fetch_and_explicit
        std::cout << "Applied mask (explicit): " << mask 
                  << ", old value: " << oldValue 
                  << ", new value: " << (oldValue & mask) << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
}

int main() {
    std::thread t1(apply_mask, 0x3F);  // 应用掩码0x3F (63)
    std::thread t2(apply_mask_explicit, 0xF0); // 应用掩码0xF0 (240)

    t1.join();
    t2.join();

    std::cout << "Final value: " << sharedValue.load() << std::endl; //输出最终值
    return 0;
}


代码解析

在上述示例中,我们展示了如何利用std::atomic_fetch_andstd::atomic_fetch_and_explicit对共享变量执行原子按位与操作。

  1. 创建原子变量

    • std::atomic<int> sharedValue{0xFF}; 创建了一个初始值为255(0xFF)的原子整型变量。
  2. 按位与的线程

    • 在 apply_mask 函数中,通过 std::atomic_fetch_and(sharedValue, mask) 对 sharedValue 执行按位与操作,并返回旧值,确保操作的原子性。
  3. 按位与的线程(显式内存序)

    • 在 apply_mask_explicit 函数中,利用 std::atomic_fetch_and_explicit(sharedValue, mask, std::memory_order_seq_cst) 指定内存序为 memory_order_seq_cst,确保全局顺序一致性。
  4. 主函数

    • 在 main 函数中,启动两个线程分别调用不同的按位与函数应用不同的掩码,并等待它们结束。
  5. 最终值显示

    • 最后输出 sharedValue 的值,展示对该变量的安全按位与操作结果。

适用场景分析

std::atomic_fetch_and和std::atomic_fetch_and_explicit的应用场景包括:

  1. 条件标志管理:在多线程环境中,用于对条件标志的原子设置和清除,确保状态只在共享线程之间按位与清晰可见。

  2. 无锁数据结构:用于构建高效的无锁数据结构,如参考计数或状态管理,保持一致的状态。

  3. 位操作:进行位掩码操作的场景,例如控制多线程下的状态位或控制不同模块的启用状态。

总结

std::atomic_fetch_andstd::atomic_fetch_and_explicit提供了强大的原子按位与功能,保证了多线程环境中资源的安全性和一致性。通过本文的示例,读者能够理解如何有效利用这些函数来管理共享资源的状态,掌握这些原子操作将有助于提升多线程应用的稳定性及性能。合理应用这些原子操作将在并发编程中显著降低复杂性,并增强代码的可靠性。

请登录后发表评论

    没有回复内容

正在唤醒异次元光景……