C++并发编程 | 原子操作std::atomic

这篇具有很好参考价值的文章主要介绍了C++并发编程 | 原子操作std::atomic。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、原子操作std::atomic相关概念

2、不加锁情况

3、加锁情况

 4、原子操作

5、总结


1、原子操作std::atomic相关概念

原子操作:更小的代码片段,并且该片段必定是连续执行的,不可分割。

1.1 原子操作std::atomic与互斥量的区别

1)互斥量:类模板,保护一段共享代码段,可以是一段代码,也可以是一个变量。

2)原子操作std::atomic:类模板,保护一个变量。

1.2 为何需要原子操作std::atomic

为何已经有互斥量了,还要引入std::atomic呢,这是因为互斥量保护的数据范围比较大,我们期望更小范围的保护。并且当共享数据为一个变量时,原子操作std::atomic效率更高。

2、不加锁情况

#include <thread>
#include <atomic> 
#include <iostream>
#include <time.h>

using namespace std;
// 全局的结果数据 
long total = 0;

// 点击函数
void click()
{
    for (int i = 0; i < 10000000; ++i)
    {
        // 对全局数据进行无锁访问 
        total += 1;
    }
}

int main(int argc, char* argv[])
{
    // 计时开始
    clock_t start = clock();
    // 创建3个线程模拟点击统计
    thread th1(click);
    thread th2(click);
    thread th3(click);
    th1.join();
    th2.join();
    th3.join();
    
    // 计时结束
    clock_t finish = clock();
    // 输出结果
    cout << "result:" << total << endl;
    cout << "duration:" << finish - start << "ms" << endl;
    return 0;
}

执行结果如下:从执行的结果来看,这样的方法虽然非常快,但是结果不正确

C++并发编程 | 原子操作std::atomic

3、加锁情况

#include <thread>
#include <atomic> 
#include <iostream>
#include <time.h>
#include <mutex>
using namespace std;
// 全局的结果数据 
long total = 0;
mutex m;
// 点击函数
void click()
{
    for (int i = 0; i < 10000000; ++i)
    {
        //加锁
        m.lock();
        // 对全局数据进行无锁访问 
        total += 1;
        //解锁
        m.unlock();
    }
}

执行结果:互斥对象的使用,保证了同一时刻只有唯一的一个线程对这个共享进行访问,从执行的结果来看,互斥对象保证了结果的正确性,但是也有非常大的性能损失,从刚才的313ms变成了现在的3858,用了原来时间的10多倍的时间。这个损失够大。

C++并发编程 | 原子操作std::atomic

 4、原子操作

#include <thread>
#include <atomic> 
#include <iostream>
#include <time.h>
using namespace std;
// 全局的结果数据 
atomic<long> total = 0;
// 点击函数
void click()
{
    for (int i = 0; i < 10000000; ++i)
    {
        // 对全局数据进行无锁访问 
        total += 1;
    }
}

结果正确!耗时只是使用mutex互斥对象的六分之一!也仅仅是不采用任何保护机制的时间的近2倍。可以说这是一个非常不错的成绩了

C++并发编程 | 原子操作std::atomic

5、总结

原子操作的实现跟普通数据类型类似,但是它能够在保证结果正确的前提下,提供比mutex等锁机制更好的性能,如果我们要访问的共享资源可以用原子数据类型表示,那么在多线程程序中使用这种新的等价数据类型,是一个不错的选择。文章来源地址https://www.toymoban.com/news/detail-425958.html

到了这里,关于C++并发编程 | 原子操作std::atomic的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 原子操作:并发编程的守护者

    并发编程的守护者在多线程或者并发编程中,我们经常需要处理一些共享资源,这时候就需要保证这些共享资源的操作是线程安全的。而原子操作就是一种能够保证线程安全的重要手段。本文将详细介绍原子操作的定义、重要性、实现原理以及应用场景。 原子操作可以被视为

    2024年01月16日
    浏览(39)
  • 《C++并发编程实战》读书笔记(4):原子变量

    标准原子类型的定义位于头文件 atomic 内。原子操作的关键用途是取代需要互斥的同步方式,但假设原子操作本身也在内部使用了互斥,就很可能无法达到期望的性能提升。有三种方法来判断一个原子类型是否属于无锁数据结构: 所有标准原子类型( std::atomic_flag 除外,因为

    2024年02月10日
    浏览(39)
  • C++并发编程:std::future、std::async、std::packaged_task与std::promise的深度探索

    1.1 并发编程的概念 (Concept of Concurrent Programming) 并发编程是一种计算机编程技术,其核心在于使程序能够处理多个任务同时进行。在单核处理器上,虽然任何给定的时间只能运行一个任务,但通过任务切换,可以创建出并发执行的效果。而在多核处理器上,可以真正同时处理

    2024年02月05日
    浏览(37)
  • 深入了解Golang atomic原子操作

       在编程中经常遇到并发而产生的问题,那么应该怎么解决并发呢?什么情况下会产生并发以及为什么会有并发问题的产生?下面我将从宏观的角度讲解并发安全性问题。    并发是指在同一时间间隔内,多个任务(线程、进程或活动)同时存在和执行的状态,在同一个

    2024年02月21日
    浏览(50)
  • C++并发编程 -3.同步并发操作

    本文介绍如何使用条件变量控制并发的同步操作、C++ 并发三剑客,函数式编程 1.概念         C++条件变量(condition variable)是一种多线程编程中常用的同步机制,用于线程间的通信和协调。它允许一个或多个线程等待某个条件的发生,当条件满足时,线程被唤醒并继续执

    2024年02月22日
    浏览(49)
  • Go并发编程 Goroutine、Channel、Select、Mutex锁、sync、Atomic等

    本文所有实例代码运行go版本: go version go1.18.10 windows/amd64 串行:所有任务一件一件做,按照事先的顺序依次执行,没有被执行到的任务只能等待。最终执行完的时间等于各个子任务之和。 并发:是以交替的方式利用 等待 某个任务的时间来处理其他任务计算逻辑,在计算机

    2024年02月07日
    浏览(52)
  • 《C++并发编程实战》读书笔记(3):并发操作的同步

    当线程需要等待特定事件发生、或是某个条件成立时,可以使用条件变量 std::condition_variable ,它在标准库头文件 condition_variable 内声明。 wait() 会先在内部调用lambda函数判断条件是否成立,若条件成立则 wait() 返回,否则解锁互斥并让当前线程进入等待状态。当其它线程调用

    2024年02月10日
    浏览(35)
  • c++并发编程实战-第4章 并发操作的同步

    想象一种情况:假设晚上坐车外出,如何才能确保不坐过站又能使自己最轻松? 这种方式存在双重浪费: 线程 th1(wait_for_flag)须不断查验标志,浪费原本有用的处理时间,这部分计算资源原本可以留给其他线程使用。 线程 th1(wait_for_flag)每次循环都需要给互斥上锁,导致

    2024年02月08日
    浏览(41)
  • 并发编程-JUC-原子类

    JUC 整体概览 原子类 基本类型-使用原子的方式更新基本类型 AtomicInteger:整形原子类 AtomicLong:长整型原子类 AtomicBoolean :布尔型原子类 引用类型 AtomicReference:引用类型原子类 AtomicStampedReference:原子更新引用类型里的字段原子类 AtomicMarkableReference :原子更新带有标记位的引

    2024年02月21日
    浏览(41)
  • JUC并发编程之原子类

    目录 1. 什么是原子操作 1.1 原子类的作用 1.2 原子类的常见操作 原子类的使用注意事项 并发编程是现代计算机应用中不可或缺的一部分,而在并发编程中,处理共享资源的并发访问是一个重要的问题。为了避免多线程访问共享资源时出现竞态条件(Race Condition)等问题,J

    2024年02月13日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包