c++11 atomic的使用详解

下面是关于"C++11 atomic的使用详解"的完整攻略。

什么是atomic

atomic是一个C++11标准中的类模板,可用于实现原子操作。原子操作是一种不可分割的操作,要么成功执行,要么不执行,不会被其他线程中断。使用atomic可以确保并发访问下的线程安全。

基础用法

atomic支持内部类型如int、long等的原子操作。下面是一些基本的示例:

#include <iostream>
#include <atomic>

int main()
{
    std::atomic<int> counter(0); // 定义原子变量

    counter.fetch_add(1); // 原子加1
    std::cout << counter.load() << std::endl; // 输出1

    counter.fetch_sub(2); // 原子减2
    std::cout << counter.load() << std::endl; // 输出-1

    counter.store(10); // 原子赋值
    std::cout << counter.load() << std::endl; // 输出10

    return 0;
}

上面的例子中,我们定义了一个原子变量counter,进行了加、减、赋值操作,并通过load()方法获取当前的值。

原子类型

C++11提供了以下几种原子类型:

  • std::atomic<bool>
  • std::atomic<char>
  • std::atomic<short>
  • std::atomic<int>
  • std::atomic<long>
  • std::atomic<long long>
  • std::atomic<unsigned char>
  • std::atomic<unsigned short>
  • std::atomic<unsigned int>
  • std::atomic<unsigned long>
  • std::atomic<unsigned long long>
  • std::atomic<void *>
  • std::atomic<std::nullptr_t>

其中,bool类型只定义了atomically useful objects,因此不能使用fetch_add等方法。

原子变量和非原子变量的转换

atomic支持与非原子类型之间的互相转换。下面是一个转换的示例:

#include <iostream>
#include <atomic>

int main()
{
    int x = 10;
    std::atomic<int> counter(x); // 原子变量赋予非原子变量的值

    std::cout << counter.load() << std::endl; // 输出10

    x = 20;
    counter.store(x); // 将非原子变量的值赋值给原子变量

    std::cout << counter.load() << std::endl; // 输出20

    return 0;
}

示例一:原子变量计数器

下面是一个使用原子变量实现线程安全计数器的示例:

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

std::atomic<int> counter(0);

void increment()
{
    for (int i = 0; i < 10000; ++i)
    {
        counter.fetch_add(1);
    }
}

int main()
{
    std::thread t1(increment);
    std::thread t2(increment);

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

    std::cout << "Counter: " << counter.load() << std::endl;

    return 0;
}

上面的例子中,我们定义了一个原子变量counter,并创建了两个线程,在每个线程中分别使用fetch_add()方法进行加1操作,各自进行一万次操作,最后输出计数器的值。

示例二:原子锁

下面是一个使用原子变量实现原子锁的示例:

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

std::atomic<bool> lock(false);

void acquire()
{
    bool expected = false;
    while (!std::atomic_compare_exchange_weak(&lock, &expected, true))
    {
        expected = false;
    }
}

void release()
{
    lock.store(false);
}

void func()
{
    acquire();
    std::cout << "Lock acquired" << std::endl;

    // 执行一些操作

    release();
    std::cout << "Lock released" << std::endl;
}

int main()
{
    std::thread t1(func);
    std::thread t2(func);

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

    return 0;
}

上面的例子中,我们定义了一个原子变量lock,使用std::atomic_compare_exchange_weak方法实现了原子锁的获取和释放操作。

总结

上面我们详细介绍了C++11中atomic的基础用法、原子类型、原子变量和非原子变量的转换,以及一些示例应用,这些内容可以帮助我们更加准确并发的控制程序。

如果有需要请参考以上攻略,具有良好的可读性和可执行性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c++11 atomic的使用详解 - Python技术站

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

相关文章

  • c++中比较好用的“黑科技”

    当提到“黑科技”时,通常指的是一些比较高级的、难以理解或者鲜为人知的技巧和方法。C++ 作为一门非常强大和复杂的编程语言,有很多这样的“黑科技”可以挖掘。下面我会详细讲解一些在 C++ 中比较好用的“黑科技”。 一、代码优化 1.1 利用符号位进行快速计算 由于在计算机中,数值的正负关系是以符号位的形式存储的。因此在某些情况下,我们可以利用符号位来进行快速计…

    C 2023年5月23日
    00
  • CDR怎么绘制一个简单的工作证?

    下面是CDR(CorelDRAW)怎么绘制一个简单的工作证的完整攻略: 1. 准备工作 首先,我们需要打开CDR软件,创建一个新的文档。在创建文档的时候,我们需要选择“页面尺寸”和“页面方向”,通常我们可以选择A4纵向的页面尺寸。 2. 绘制证件模板 接下来,我们需要绘制一个证件的矩形框架作为证件的模板。首先,我们需要选择矩形工具(快捷键F6),在画布上绘制…

    C 2023年5月23日
    00
  • 详解C++中的自动存储

    标题:详解C++中的自动存储 自动存储是 C++ 中的一个关键概念,它是指当程序进入一个特定的代码块时,在该块内声明的变量会自动被创建并分配存储空间,当程序退出该块时,这些变量也会自动被销毁并释放空间。这种存储方式在 C++ 中被广泛使用,也是 C++ 中最基本的存储类型之一。 自动存储的特点 自动存储是默认的存储类型。 自动存储的变量只在其所在作用域内可见…

    C 2023年5月23日
    00
  • 2017电视盒子排行榜,年度最畅销的五大旗舰

    2017电视盒子排行榜,年度最畅销的五大旗舰 随着网络时代的到来,各种智能设备在人们的生活中越来越普及,其中最受欢迎的无疑是电视盒子。2017年是智能电视盒子快速发展的一年,各大品牌纷纷推出了旗舰产品,经过消费者的考验,下面是2017年度最畅销的五大旗舰电视盒子排行榜: 小米盒子 创维盒子 天猫魔盒 极米盒子 海美迪盒子 1. 小米盒子 小米盒子采用了小米自…

    C 2023年5月22日
    00
  • 辐射4人员属性设定详细分析

    辐射4人员属性设定详细分析 在辐射4中,人员属性设定对游戏的角色扮演和流程起着很大的作用。本文将详细分析人员属性设定的每个部分,并提供一些有用的技巧和建议。 S.P.E.C.I.A.L S.P.E.C.I.A.L.代表了Strength(力量)、Perception(感知)、Endurance(耐力)、Charisma(魅力)、Intelligence(智力…

    C 2023年5月22日
    00
  • 浅谈C#中List对象的深度拷贝问题

    首先我们先介绍一下深度拷贝和浅拷贝的概念。 浅拷贝是指直接复制对象的指针,两个对象指向同一个内存地址,当一个对象改变时,另一个对象也会一起改变。 深度拷贝是指复制一个对象,重新分配一块内存地址给新的对象,两个对象的内存地址不同,修改其中一个对象不会影响另一个对象。 在C#中,List对象是一个常用的集合,我们来拿它作为例子进行说明。 如何实现List对象的深…

    C 2023年5月22日
    00
  • MFC实现学生选课系统

    MFC实现学生选课系统攻略 1. 前言 学生选课系统是大学教学管理系统中必不可少的一部分,本文介绍如何使用MFC来实现一个学生选课系统,包括系统框架设计、用户界面设计以及基本功能实现等部分内容。 2. 系统框架设计 2.1 整体思路 学生选课系统主要包含两个模块:学生信息管理模块和课程信息管理模块。首先需要创建一个主窗口来容纳所有的子窗口,并通过主窗口提供菜…

    C 2023年5月23日
    00
  • win2008 R2服务器下修改MySQL 5.5数据库data目录的方法

    修改MySQL 5.5数据库data目录的方法需要按照以下步骤进行。 步骤1:备份原有数据 在修改数据目录之前,首先需要备份原有数据。可以使用mysqldump命令,将原有数据导出到其他文件或目录中。 示例: mysqldump -u root -p dbname > dbname.sql 以上命令中,-u 参数指定用户名,-p 参数后面跟着密码,db…

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