首页 > 编程语言 >C++原子变量atomic详解

C++原子变量atomic详解

时间:2023-09-27 21:45:58浏览次数:28  
标签:relaxed C++ 详解 atomic memory true order store

b站视频
文章1

C++中原子变量确保共享变量的操作在执行时不会被其他线程的操作干扰。
无法复制/移动对象。

is_lock_free函数:atomic对象是否支持无锁操作(什么意思?如果atomic对象需要锁,那设为atomic对象的意义是什么?)

std::atomic_flag 是 C++ 中的一个原子布尔类型,它用于实现原子锁操作。什么叫原子锁?

有没有锁,有什么影响吗?
原子操作也不见得是无锁的,使用is lock free和is always lock free
进行判断。

memory_order

atomic对象可以通过指定不同的memory orders来控制其对其他非原子对象的访问顺序和可见性,从而实现线程安全。常用的memory orders包括(参考:链接):

memory_order_relaxed

memory_order_relaxed: 无序的内存访问,允许编译器做更多的优化。

#include<bits/stdc++.h>
#include<thread>
using namespace std;

atomic<bool> x,y;
atomic<int> z;
void write_x_then_y()
{
    x.store(true, memory_order_relaxed);
    y.store(true, memory_order_relaxed);
}
void read_y_then_x()
{
    while(!y.load(memory_order_relaxed));  // y为true时会退出while
    if (x.load(memory_order_relaxed))    // x也为true时,z的值会改变
        ++z;
}

int main() {
    x=false;
    y=false;
    z=0;
    thread a(write_x_then_y);
    thread b(read_y_then_x);
    a.join();
    b.join();
    cout <<  noboolalpha << (z.load()!=0) << endl;
}

仅保证该原子类型变量的操作是原子化的,write_x_then_y()中对x和y的赋值是无序的,也就是说可能出现先给y赋值然后给x赋值,也可能出现先给x赋值然后给y赋值。所以read_y_then_x()中可能出现y为true,但x不为true的情况。(我的理解)
对上面代码进行实际测试,并没有出现y为true但x不为true的情况。这不能说明问题,因为其他编译器的优化策略,可能会导致出现y为true但x不为true的情况。

memory_order_release与memory_order_acquire

memory_order_release:

#include<bits/stdc++.h>
#include<thread>
using namespace std;

atomic<bool> x,y;
atomic<int> z;
// void write_x_then_y()
// {
//     x.store(true, memory_order_relaxed);
//     y.store(true, memory_order_release);
// }
// 下面函数和上面函数等价
void write_x_then_y()
{
    x.store(true, memory_order_relaxed);
    atomic_thread_fence(memory_order_release);
    y.store(true, memory_order_relaxed);
}

void read_y_then_x()
{
    while(!y.load(memory_order_acquire));  // y为true时会退出while
    if (x.load(memory_order_relaxed))    // x也为true时,z的值会改变
        ++z;
}

int main() {
    x=false;
    y=false;
    z=0;
    thread a(write_x_then_y);
    thread b(read_y_then_x);
    a.join();
    b.join();
    cout <<  noboolalpha << (z.load()!=0) << endl;
}

y.store(true, memory_order_release);保证了此语句前的语句写入完成。y.load(memory_order_acquire)用来“接住”使用memory_order_release写入的y。由于y.store(true, memory_order_release);保证了此语句前的语句写入完成,所以y.load(memory_order_acquire)后面的语句读取到的x都写入完成的x。(我的理解)

memory_order_seq_cst

memory_order_seq_cst是原子操作的默认参数,代码的顺序是怎么样的,底层的内存访问顺序就是怎么样的。(我的理解)

memory_order_consume

编译器一般都不怎么支持memory_order_consume,它保证本次读取之前所有依赖于该原子类型变量值的操作都已完成,但不保证其他线程对该变量的存储结果已经可见。(看不太懂)

自定义类型作为原子类型

atomic:T可以是自定类型,不过有以下注意点:

必须使用编译器生成的复制构造函数?
不可以有虚函数或继承虚类
operator=等价与operator& ?

如下是否是懒汉式?:
Singleton& Singleton::getInstance() {
static Singleton obj;
return obj;
}

标签:relaxed,C++,详解,atomic,memory,true,order,store
From: https://www.cnblogs.com/codingbigdog/p/17734402.html

相关文章

  • Effective Modern C++
     作者针对C++11/14而写的 EffectiveModernC++简介-EffectiveModernC++(cntransgroup.github.io)  一篇文章学完EffectiveModernC++:条款&实践-知乎(zhihu.com) ......
  • 每一个C++开发者都应该知道的线上工具
      每一个C++开发者都应该知道的线上工具-知乎(zhihu.com) 要想代码写得丝滑,怎么可以不熟练各种开发工具呢?锤子用的好,烦恼会减少。这里推荐几个C++开发中用于编译、构建、调试和性能分析的线上工具,最初的资料来源于LightningTalk:OnlineToolsEveryC++DevelopersSh......
  • C++(命名空间,输入输出)
    从堆上申请空间#include<malloc.h>int*p=(int)malloc(10sizeof(int));//malloc返回的是无类型free(p);//释放内存,不然会造成内存泄漏命名空间:用户自己定义的作用域namespaceN{//变量inta;//函数}inta;//不冲突命名空间可以嵌套在一个工程中,可以出现多个相同名称的命名......
  • 【详解】Spring Boot + Mybatis-Plus实现CRUD,轻松玩转接口操作!
    ......
  • .NET Core|--调用C++库|--LibraryImport docker环境下,处理依赖问题--GCC--Docker
    前言万恶之源在于,C#程序中需要调用C++的一个函数库,在Windows环境下,只要保证引用的相关dll存在,就是ok的,但是在Linux环境下,并且我的Webapi程序是部署在docker中的,问题就比较麻烦一些.经历了新建软链接,缺失".so"文件,有了".so"文件后,版本错误:libstdc++.so.......
  • c++正则表达式汇总
    一、校验字符的表达式1汉字:^[\u4e00-\u9fa5]{0,}$2英文和数字:^[A-Za-z0-9]+或[A−Za−z0−9]4,403长度为3-20的所有字符:^.{3,20}$4由26个英文字母组成的字符串:^[A-Za-z]+$5由26个大写英文字母组成的字符串:^[A-Z]+$6由26个小写英文字母组成的字符串:^[a-z]+$7由数字......
  • C++多线程Multithreading std::condition_variable
    多线程Multithreading#include<iostream>#include<thread>#include<mutex>#include<condition_variable>std::mutexmtx;std::condition_variablecv;boolisOdd=true;voidprintOdd(){for(inti=1;i<=100;i+=2){......
  • 分布式事务详解
    1、分布式事务传统数据库事务事务特性:ACID1、原子性:事务中的所有操作,要么全部成功,要么全部失败,影响事务的操作,一般指的是增删改,也就是一个事务中,有多个增删改的SQL2、一致性:事务开始前到事务结束后,数据状态需要一致。这意味着事务中的操作必须满足数据库定义的所有约束和规则,......
  • 【从0学习Solidity】 3. 函数详解
    【从0学习Solidity】3.函数详解博主简介:不写代码没饭吃,一名全栈领域的创作者,专注于研究互联网产品的解决方案和技术。熟悉云原生、微服务架构,分享一些项目实战经验以及前沿技术的见解。关注我们的主页,探索全栈开发,期待与您一起在移动开发的世界中,不断进步和创造!本文收录于不写代......
  • c#装饰器模式详解
    基础介绍:  动态地给一个对象添加一些额外的职责。适用于需要扩展一个类的功能,或给一个类添加多个变化的情况。  装饰器,顾名思义就是在原有基础上添加一些功能。  大家都只知道如果想单纯的给原有类增加一些功能,可以直接继续该类生成一个子类就可以。  举个例子,如果现......