C++原子操作,有人确定知道怎么使用吗?

C++ std::atomic 原子操作介绍

std::atomic 是 C++11 引入的一个模板类,用于提供对单个变量或对象进行原子操作的能力。原子操作是不可分割的,即操作在执行过程中不会被线程调度机制中断。这对于多线程编程中的同步和数据一致性至关重要。

std::atomic 可以应用于基本数据类型(如 bool、int、float 等)以及用户自定义类型(需要满足特定的条件)。std::atomic 提供了多种成员函数,如 load()、store()、exchange()、compare_exchange_weak()、compare_exchange_strong()、fetch_add()、fetch_sub() 等,用于执行各种原子操作。

原子操作的使用场景

  1. 无锁编程:在多线程程序中,使用 std::atomic 可以避免使用互斥锁(std::mutex)等同步机制,从而减少上下文切换和锁竞争的开销。
  2. 计数器:实现线程安全的计数器,如统计某个操作的执行次数。
  3. 标志位:用于控制线程的执行流程,如设置完成标志、停止标志等。
  4. 状态变量:保护共享状态变量,确保该状态变量在多线程环境下的一致性和可见性。

以下给出二个原子操作的使用示例。

示例 1:原子计数器

#include <iostream>  
#include <thread>  
#include <vector>  
#include <atomic>  
  
std::atomic<int> g_counter(0);  
  
void increment(int n) {  
    for (int i = 0; i < n; ++i) {  
        g_counter.fetch_add(1, std::memory_order_relaxed);  
    }  
}  
  
int main() {  
    const int num_threads = 10;  
    const int iterations = 1000;  
  
    std::vector<std::thread> threads;  
  
    for (int i = 0; i < num_threads; ++i) {  
        threads.emplace_back(increment, iterations);  
    }  
  
    for (auto& t : threads) {  
        t.join();  
    }  
  
    std::cout << "Final counter value: " << g_counter << std::endl;  
  
    return 0;  
}

在这个例子中,我们创建了一个原子计数器 g_counter,并启动了多个线程去增加它的值。每个线程都执行了 increment 函数,该函数通过 fetch_add 方法以原子方式增加计数器的值。

最后,等待所有线程完成,并打印出计数器 g_counter 的最终结果值。

示例 2:使用 compare_exchange_weak 实现自旋锁

#include <iostream>  
#include <thread>  
#include <atomic>  
  
std::atomic<bool> g_lock(false);  
  
void critical_section() {  
    bool expected = false;  
    while (!g_lock.compare_exchange_weak(expected, true, std::memory_order_acquire)) {  
        expected = false;  
    }  
  
    // 临界区代码  
    std::cout << "Entered critical section by thread " << std::this_thread::get_id() << std::endl;  
  
    // 释放锁  
    g_lock.store(false, std::memory_order_release);  
}  
  
int main() {  
    std::thread t1(critical_section);  
    std::thread t2(critical_section);  
  
    t1.join();  
    t2.join();  
  
    return 0;  
}

在这个例子中,我们使用 std::atomic 类型的 g_lock 变量来实现一个简单的自旋锁。

compare_exchange_weak 方法尝试将 lock 的值从 expected(预期值)更改为 true(锁定状态),如果 g_lock 的当前值等于 expected,则操作成功,线程进入临界区;否则,循环重试。需要注意一点,compare_exchange_weak 可能由于伪失败(spurious failure)而失败,即使没有其他线程修改 g_lock 的值,因此通常需要在循环中重试,确保最终操作成功。

最后,在临界区执行完毕后,通过 store 方法将 g_lock 设置为 false,释放锁。

-End-

#想了解更多精彩内容,关注下方公众号。

本人开发小杨哥:

超20年C++开发经验,独立软件开发。著名开源产品MYCP(高并发C++通信应用服务器)作者,和WordBN字远笔记共享软件产品作者。

长期招C++、Qt编程学员,欢迎加好友咨询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天恩软件工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值