使用 memory_order_seq_cst 输出 10

如何解决使用 memory_order_seq_cst 输出 10

当我运行这个程序时,我得到的输出为 10,这对我来说似乎是不可能的。我在 x86_64 核心 i3 ubuntu 上运行它。

如果输出是 10,那么 1 一定来自 c 或 d。

同样在线程 t[0] 中,我们将 c 赋值为 1。现在 a 是 1,因为它发生在 c=1 之前。 c 等于被线程 1 设置为 1 的 b。所以当我们存储 d 时,它应该是 1,因为 a=1。


  • 可以使用 memory_order_seq_cst 输出 10 吗?我尝试在第一行(变量 =1 )和第二行(printf)之间的两个线程上插入 atomic_thread_fence(seq_cst) 但它仍然没有工作。

取消注释 围栏 不起作用。 尝试使用 g++clang++ 运行。两者都给出相同的结果。

#include<thread>
#include<unistd.h>
#include<cstdio>
#include<atomic>
using namespace std;

atomic<int> a,b,c,d;

void foo(){
        a.store(1,memory_order_seq_cst);
//        atomic_thread_fence(memory_order_seq_cst);
        c.store(b,memory_order_seq_cst);
}

void bar(){
        b.store(1,memory_order_seq_cst);
  //      atomic_thread_fence(memory_order_seq_cst);
        d.store(a,memory_order_seq_cst);
}

int main(){
        thread t[2];
        t[0]=thread(foo); t[1]=thread(bar);
        t[0].join();t[1].join();
        printf("%d%d\n",c.load(memory_order_seq_cst),d.load(memory_order_seq_cst));
}
bash$ while [ true ]; do ./a.out | grep "10" ; done 
10
10
10
10

解决方法

10 (c=1,d=0) 很容易解释:bar 恰好先运行,并在 foo 读取 b 之前完成。

在不同内核上启动线程的内核间通信的怪癖意味着即使 thread(foo) 首先在主线程中运行,也很容易发生这种情况。例如也许一个中断到达了操作系统为 foo 选择的核心,延迟了它实际进入该代码1

请记住,seq_cst 仅保证所有 seq_cst 操作存在某个总顺序,该顺序与每个线程内的先序顺序兼容。 (以及由其他因素建立的任何其他发生在之前的关系)。因此,以下原子操作顺序是可能的,甚至无需将 bar 中的 a.load2 与结果 int 临时的 d.store 分开。

        b.store(1,memory_order_seq_cst);   // bar1.  b=1
        d.store(a,memory_order_seq_cst);   // bar2.  a.load reads 0,d=0

        a.store(1,memory_order_seq_cst);   // foo1
        c.store(b,memory_order_seq_cst);   // foo2.  b.load reads 1,c=1
// final: c=1,d=0

atomic_thread_fence(seq_cst) 对任何地方都没有影响,因为您的所有操作都已经是 seq_cst 栅栏基本上只是停止对该线程操作的重新排序;它不会等待或与其他线程中的栅栏同步。

(只有看到另一个线程存储的值的加载才能创建同步。但是这样的加载不会等待另一个存储;它无法知道还有另一个存储。如果你想继续加载直到你看到你期望的值,你必须写一个自旋等待循环。)


脚注 1: 由于您所有的原子变量可能都在同一个缓存行中,即使执行确实在两个不同的内核上同时到达了 foobar 的顶部,错误共享也可能会让两者来自一个线程的操作发生,而另一个核心仍在等待获得独占所有权。尽管 seq_cst 存储足够慢(至少在 x86 上),硬件公平性的东西可能会在提交 1 的第一个存储后放弃独占所有权。无论如何,一个线程中的两个操作在另一个线程之前发生并获得 10 或 01 的很多方法。如果我们获得 11,甚至可能获得 b=1 则 {{ 1}} 在任一加载之前。使用 seq_cst 确实会阻止硬件提前加载(在 store 全局可见之前),因此很有可能。

脚注 2:裸 a=1 的左值到右值评估使用重载的 a 转换,它等效于 (int)。来自 a.load(seq_cst) 的操作可能发生在该加载和从中获取临时值的 foo 之间。 d.store 不是原子副本;它相当于 d.store(a) int tmp = a;。这不需要解释您的观察结果。

,

printf 语句是不同步的,所以 10 的输出可能只是一个重新排序的 01。
01 发生在 printf 之前的函数串行运行时。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res