并发:C++11 内存模型中的原子性和易失性

2024-05-13

全局变量在 2 个不同内核上的 2 个并发运行的线程之间共享。线程对变量进行写入和读取。对于原子变量,一个线程可以读取过时的值吗?每个核心可能在其缓存中具有共享变量的值,并且当一个线程写入缓存中的其副本时,不同核心上的另一个线程可能会从其自己的缓存中读取过时的值。或者编译器执行强内存排序以从其他缓存读取最新值? c++11 标准库具有 std::atomic 支持。这与 volatile 关键字有何不同?在上述场景中,易失性类型和原子类型的行为有何不同?


首先,volatile并不意味着原子访问。它专为内存映射 I/O 和信号处理等任务而设计。volatile与使用时完全没有必要std::atomic,除非您的平台另有说明,volatile与线程之间的原子访问或内存排序无关。

如果您有一个在线程之间共享的全局变量,例如:

std::atomic<int> ai;

那么可见性和排序约束取决于您用于操作的内存排序参数,以及锁、线程和对其他原子变量的访问的同步效果。

在没有任何额外同步的情况下,如果一个线程向ai那么没有什么可以保证另一个线程在任何给定时间段内都能看到该值。该标准规定它应该“在合理的时间内”可见,但任何给定的访问都可能返回陈旧的值。

默认内存顺序为std::memory_order_seq_cst为所有人提供单一的全球总订单std::memory_order_seq_cst跨所有变量的操作。这并不意味着您无法获得过时的值,但它确实意味着您获得的值决定了您的操作在整个顺序中的位置。

如果你有2个共享变量x and y,最初为零,并让一个线程将 1 写入x另一个写 2 到y,那么读取两者的第三个线程可能会看到 (0,0)、(1,0)、(0,2) 或 (1,2),因为操作之间没有顺序约束,因此操作可能会出现以全局顺序中的任何顺序。

如果两个写入都来自同一个线程,则x=1 before y=2读取线程读取y before x那么 (0,2) 不再是一个有效的选项,因为读取y==2意味着较早写入x是可见的。其他 3 个配对 (0,0)、(1,0) 和 (1,2) 仍然是可能的,具体取决于 2 个读取与 2 个写入的交错方式。

如果您使用其他内存顺序,例如std::memory_order_relaxed or std::memory_order_acquire那么约束就会进一步放松,单一的全局排序不再适用。如果没有额外的同步,线程甚至不必就两个存储的顺序达成一致以分隔变量。

保证您拥有“最新”值的唯一方法是使用读取-修改-写入操作,例如exchange(), compare_exchange_strong() or fetch_add()。读取-修改-写入操作有一个额外的约束,即它们始终对“最新”值进行操作,因此一系列ai.fetch_add(1)一系列线程的操作将返回一系列没有重复或间隙的值。在没有附加约束的情况下,仍然无法保证哪些线程会看到哪些值。特别要注意的是,使用 RMW 操作不会强制其他线程的更改更快地变得可见,这只是意味着如果更改是not如果 RMW 看到,那么所有线程必须同意它们在该原子变量的修改顺序中比 RMW 操作晚。来自不同线程的存储仍然可以延迟任意时间,具体取决于 CPU 何时actually将存储发布到内存(而不仅仅是其自己的存储缓冲区),身体上的执行线程的 CPU 之间的距离有多远(在多处理器系统的情况下),以及缓存一致性协议的详细信息。

使用原子操作是一个复杂的主题。我建议您阅读大量背景材料,并在使用原子编写生产代码之前检查已发布的代码。在大多数情况下,编写使用锁的代码会更容易,而且效率也不会明显降低。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

并发:C++11 内存模型中的原子性和易失性 的相关文章

  • C++ 长 switch 语句还是用地图查找?

    在我的 C 应用程序中 我有一些值充当代表其他值的代码 为了翻译代码 我一直在争论使用 switch 语句还是 stl 映射 开关看起来像这样 int code int value switch code case 1 value 10 b
  • 检测wlan是否关闭

    任何人都可以给我一个提示 如何在 Windows Phone 上以编程方式检测 C 8 1 应用程序 不是 8 0 是否启用 禁用 WLAN 我不想更改这些设置 只是需要知道 该解决方案是一个 Windows 8 1 通用应用程序 Wind
  • 如何在CUDA应用程序中正确应用线程同步?

    一般来说 我在应用程序中偶尔会使用线程同步 因为我并不经常需要此功能 我并不是真正的高级 C C 程序员 但我也不是初学者 我开始学习 CUDA C 对当今 GPU 与 CPU 的能力相比感到兴奋 我意识到 CUDA 编程主要是关于并行线程
  • 是否存在指向不同类型的指针具有不同大小的平台?

    C 标准允许指向不同类型的指针具有不同的大小 例如sizeof char sizeof int 是允许的 但是 它确实要求如果将指针转换为void 然后转换回其原始类型 它必须与其原始值进行比较 因此 从逻辑上来说 sizeof void
  • 在开关中使用“goto”?

    我看到了一个建议的编码标准 内容如下Never use goto unless in a switch statement fall through 我不跟 这个 例外 案例到底是什么样的 这证明了goto 此构造在 C 中是非法的 swi
  • 如何制作可启动程序?

    所以 这个问题可能看起来很奇怪 但假设我编译了 int main void int x 3 int y 4 int z x y 是否可以让CPU这样运行 如何 例如 这允许我写入监视器吗 如果我没记错的话 内存中有些地方可以写入要显示的内容
  • 计算另一个表达式中的 C# 表达式

    我想在另一个表达式中使用一个表达式 Expression
  • 使用并行任务库时“foreach”失败

    以下代码创建正确数量的文件 但每个文件都包含第一个列表的内容 有人能发现我做错了什么吗 private IList
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 使用查询表达式对 List 进行排序

    我在使用 Linq 订购这样的结构时遇到问题 public class Person public int ID get set public List
  • 如何在三个 IEnumerable 上使用 Zip [重复]

    这个问题在这里已经有答案了 可能的重复 使用 Linq 从 3 个集合创建项目 https stackoverflow com questions 5284315 create items from 3 collections using
  • 使用 GCC 生成可读的程序集?

    我想知道如何使用GCC http en wikipedia org wiki GNU Compiler Collection在我的 C 源文件中转储机器代码的助记符版本 这样我就可以看到我的代码被编译成什么 你可以使用 Java 来做到这一
  • 在 OpenGL 中渲染纹理 1 到 1

    所以我想做的是使用 OpenGL 和 C 将纹理渲染到平面上 作为显示图像的一种方式 但是我需要确保在渲染纹理时没有对纹理进行任何处理 抗锯齿 插值 平滑 模糊等 这是 OpenGL 处理渲染纹理的默认方式吗 或者是否需要设置一些标志才能禁
  • ASP.NET MVC 路由:如何从 URL 中省略“索引”

    我有一个名为 StuffController 的控制器 具有无参数索引操作 我希望从表单中的 URL 调用此操作mysite com stuff 我的控制器定义为 public class StuffController BaseContr
  • 逆向工程 ASP.NET Web 应用程序

    我有一个 ASP NET Web 应用程序 我没有源代码 该 bin 包含 10 个程序集和一个 compiled 文件 我在 App Code dll 上使用 Reflector 它向我显示了类和命名空间之类的东西 但它太混乱了 有没有什
  • 如何停止无限循环?

    我正在编写一个程序 该程序将计算三角形或正方形的面积 然后提示用户是否希望计算另一个 我的代码已经运行到可以计算任一形状的面积的程度 但随后不再继续执行代码的其余部分 例如 如果选择了正方形 则计算面积 然后返回到正方形边长的提示 我假设这
  • PyQt 中的线程和信号问题

    我在 PyQt 中的线程之间进行通信时遇到一些问题 我使用信号在两个线程 发送者和监听者 之间进行通信 发送者发送消息 期望被监听者接收 但是 没有收到任何消息 谁能建议可能出了什么问题 我确信这一定很简单 但我已经环顾了几个小时但没有发现
  • 如何得知客户端从服务器的下载速度?

    根据客户的下载速度 我想以低质量或高质量显示视频 任何 Javascript 或 C 解决方案都是可以接受的 Thanks 没有任何办法可以确定 您只能测量向客户端发送数据的速度 如果没有来自客户端的任何类型的输入来表明其获取信息的速度 您
  • 结构化绑定的用例有哪些?

    C 17 标准引入了新的结构化绑定 http en cppreference com w cpp language structured binding功能 最初是proposed http www open std org jtc1 sc
  • 在并行包中的 R 的 par*apply 函数内部使用 Rcpp 函数

    我试图了解背后发生的事情Rcpp sourceCpp 调用并行环境 最近 问题中部分解决了这个问题 在 Windows 上使用 parLapply 中的 Rcpp 函数 https stackoverflow com questions 2

随机推荐

  • 如何向 SvelteKit/Vite 应用添加版本号?

    我正在尝试在我的 SvelteKit 应用程序中创建一个系统 它会在某个页面上向您显示有关当前应用程序版本的信息 最好是 Git 提交哈希和描述 我尝试使用Vite的定义功能 https vitejs dev config define在构
  • Android On Focus Listener 和 On Click Listener on ImageView

    我有一个 imageview 它具有两个属性 可聚焦的 and 可聚焦触摸模式 set to true
  • 如何解释 mgcv 的随机效应图

    我有一些关于在 GAM 中使用随机效果的问题 首先 您如何解释和传达输出图 我在这个 GAM 中将火灾建模为随机效应 因为它在我的不同现场站点上很大程度上是随机发生的 并且我只将其记录为二进制 它不能作为普通变量工作 因为它的级别太少 而且
  • Cakephp - CSRF 令牌不匹配

    我在 Cakephp 3 6 中有一个项目 其中 MessageController 中的 3 个操作由 Ajax 调用 但是 我有一个问题 当我向其中一个操作发送请求时 XHR 会向我返回以下内容 message CSRF token m
  • 带有 .htaccess 的漂亮网址?

    我刚刚创建了一个新的 WordPress 页面模板 在其中运行一些 php mysql 脚本 我想对其子页面应用 mod 重写 例如我生成了以下链接 http www quotist com quotes by authors html l
  • 首选项和操作栏中的开/关切换按钮 - 冰淇淋三明治风格

    我指的是 ICS 手机上默认 Android 设置应用程序中看到的蓝色开 关样式 也可以在这里看到 http android developers blogspot com 2012 02 android design v2 now wit
  • java中的回调是什么[重复]

    这个问题在这里已经有答案了 可能的重复 什么是回调函数 https stackoverflow com questions 824234 what is a callback function 我已经阅读了回调的维基百科定义 但我仍然没有明
  • 如何将十六进制字符串转换为十进制值

    我尝试将十六进制字符串转换为十进制值 但它没有给我预期的结果 I tried convert toint32 hexa 16 convert todecimal hexa 我有一个看起来像这样的字符串 1 12 94 201 198 我把它
  • 按下按钮即可持续移动

    我按照在线教程制作了一个贪吃蛇游戏 并需要一些帮助来进行一些更改 截至目前 holding向左或向右箭头键将使蛇移动 它能让蛇向左或向右移动吗只需轻按一下按钮所以用户不必按住箭头键 question True while not gameE
  • 获取 Promise 的值并分配给变量

    utility fetchInfo 返回一个 Promise 对象 我需要能够获取此 Promise 对象的值 并将其值分配给一个变量 以便稍后在我的代码中使用 此刻 我可以愉快地打印出result到控制台 但我需要能够将此值分配给myVa
  • 重载逻辑运算符 && 和 ||从 C++17 开始短路?

    我读到http en cppreference com w cpp language operators http en cppreference com w cpp language operators 布尔逻辑运算符 运算符 和运算符
  • 如何将存储过程中的值返回到 EF

    我试图通过 EF 调用存储过程并从存储过程中检索返回值 我用过this https stackoverflow com questions 6861737 executesqlcommand with output parameter an
  • 角度指令忽略非数字输入

    我必须为 IE8 编写一些代码 我有一个 ng repeat 创建一个表 其中包含
  • .NET IExtenderProvider (C#)

    我正在尝试延长TextBox ComboBox and Panel控制使用IExtenderProvider但我无法让它正常工作 我开始相信我还没有完全理解这个概念 有人知道网络上有什么好的资源 带有示例 吗 IExtenderProvid
  • 背景图像上的透明导航栏

    我试图找出让我的英雄 背景图像位于透明 Bootstrap 4 导航栏后面的最佳方法 一些建议是将背景图像应用到页面的 这是可行的 但我不希望应用程序内的所有其他静态页面上都有背景图像 只有登陆页面 Rails 应用程序 我尝试在导航栏和
  • Swift - 停止 avaudioplayer

    我正在尝试将音板构建到应用程序中 并找到了一种使用标签来控制播放声音的有效方法 不过 我现在正在尝试集成一个可以与 stop 方法上的AVAudioPlayer但是我当前的代码出现错误 EXC BAD ACCESS 这就是我现在正在使用的
  • 我们可以预测 Hive SELECT * 查询结果的顺序吗?

    是否有可能a的结果的顺序SELECT query no ORDER BY 如果使用相同的 DBMS 作为 Metastore 那么总是相同的吗 所以 只要使用MySQL作为Metastore 结果的顺序就为aSELECT 查询将始终相同 如
  • SSIS使用列位置而不是名称导入Excel文档

    我想知道是否可以通过按位置引用列来使用 SSIS 导入 Excel 文档 例如 导入列 A D M AA 等 我问这个问题是因为我需要从第三方加载多个 Excel 文档 每个文档在相应的列中包含相同的数据类型 但每个文档的列名称不同 Tha
  • Django 跨反向关系聚合

    鉴于这两个模型 class Profile models Model user models ForeignKey User unique True verbose name user about models TextField abou
  • 并发:C++11 内存模型中的原子性和易失性

    全局变量在 2 个不同内核上的 2 个并发运行的线程之间共享 线程对变量进行写入和读取 对于原子变量 一个线程可以读取过时的值吗 每个核心可能在其缓存中具有共享变量的值 并且当一个线程写入缓存中的其副本时 不同核心上的另一个线程可能会从其自