第十一节std::atomic原子操作

本文深入探讨了原子操作在多线程编程中的应用,包括其概念、实现方式以及如何避免线程间的数据竞争。通过实例展示了std::atomic的使用,解释了合法操作符,并分享了一点心得,适用于计数或统计场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、原子操作

1.1原子操作概念例子

互斥量:多线程编程中保护共享数据:锁,操作共享数据,开锁

有两个线程,对一个变量进行操作,这个线程读,另一个线程往变量中写值。

int atomvalue = 5;

读线程A:

int tmpvalue = atomvalue;//atomvalue代表的是多个线程之间要共享的变量

写线程B:

atomvalue = 6;

结果:读出一个不可预料的中间值

原子操作:
可以把原子操作理解为一种:不需要用到互斥量加锁(无锁)技术的多线程编程方式
多线程中不会被打断程序执行片段

互斥量:加锁一般针对一个代码段(几行代码)
原子操作:针对的一般都是一个变量,而不是一个代码段
一般指“不可分割的操作”
std::atomic来代表原子操作,std::atomic是个类模板。其实std::atomic这个东西是用来封装某个类型的值的

#include <thread>
#include <atomic>

std::atomic<int> g_mycount;

void mythread()
{
    for (int i = 0;i < 10000000;i++)
    {
        g_mycount++;
    }
    return;
}

int main()
{
    std::thread myobj1(mythread);
    std::thread myobj2(mythread);
    myobj1.join();
    myobj2.join();
    cout << "两个线程执行完毕,最终的g_mycount的结果是: " << g_mycount << endl;
}

结果:

两个线程执行完毕,最终的g_mycount的结果是: 20000000

注意:
不能写成std::atomic<int> g_mycount = 0;,否则

error: use of deleted function ‘std::atomic<int>::atomic(const std::atomic<int>&)’
 std::atomic<int> g_mycount = 0;
std::atomic<bool> g_ifend;

void mythread()
{
    std::chrono::milliseconds dura(1000);
    while (g_ifend == false)
    {
        cout << "thread id = " << std::this_thread::get_id() << "运行中..." << endl;
        std::this_thread::sleep_for(dura);
    }
    cout << "thread id = " << std::this_thread::get_id() << "运行结束..." << endl;
    return;
}

int main()
{
    std::thread myobj1(mythread);
    std::thread myobj2(mythread);
    std::chrono::milliseconds dura(5000);
    std::this_thread::sleep_for(dura);
    g_ifend = true;
    myobj1.join();
    myobj2.join();
    cout << "程序执行完毕,退出" << endl;
    return 0;
}

结果

thread id = thread id = 140104806115072140104797722368运行中...运行中...

thread id = 140104806115072运行中...
thread id = 140104797722368运行中...
thread id = 140104806115072运行中...
thread id = 140104797722368运行中...
thread id = 140104806115072运行中...
thread id = 140104797722368运行中...
thread id = 140104806115072运行中...
thread id = 140104797722368运行中...
thread id = 140104806115072运行结束...
thread id = 140104797722368运行结束...
程序执行完毕,退出

1.2 一点心得

一般用于计数或者统计(累计发出了多少个数据包,累计接受到了多少数据包)

二、原子操作续谈

2.1 合法操作符

一般atomic原子操作,针对++,–,+=,&=,|=,^=

cout << atm << endl; 读atm是个原子操作,但整个一行代码并不是原子操作;屏幕看到的atm并不是atm的最新值

2.2 赋值

atuo atm2 = atm;

原子变量这种定义不允许,显示“尝试引用已删除的函数”
load()以原子方式读atomic对象的值:

atomic<int> atm2(atm.load());

store()以原子方式写入内容:

atm2.store();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值