gpt4 book ai didi

linux - 为什么下面的代码无法输出 Hello World?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:17:29 25 4
gpt4 key购买 nike

为什么下面的代码不能输出Hello World!跟CPU缓存有关系吗?但是我觉得CPU应该保证缓存的一致性吧? thread_fun2 修改值后,thread_fun 是否应该从内存中刷新缓存。我知道 atomic 可以解决这个问题,但我不知道为什么下面的代码不起作用。

#include <stdio.h>
#include <thread>
int a = 4;

void thread_fun() {
while(a!=3) {

}
printf("Hello world!\n");
}
void thread_fun2() {
a=3;
printf("Set!\n");
}


int main() {
auto tid=std::thread(thread_fun);
auto tid2=std::thread(thread_fun2);
tid.join();
tid2.join();
}

构建选项:

g++ -o multi multi.cc -O3 -std=c++11 -lpthread

下面是gdb输出

(gdb) disass thread_fun
Dump of assembler code for function _Z10thread_funv:
0x0000000000400af0 <+0>: cmpl $0x3,0x201599(%rip) # 0x602090 <a>
0x0000000000400af7 <+7>: je 0x400b00 <_Z10thread_funv+16>
0x0000000000400af9 <+9>: jmp 0x400af9 <_Z10thread_funv+9>
0x0000000000400afb <+11>: nopl 0x0(%rax,%rax,1)
0x0000000000400b00 <+16>: mov $0x401090,%edi
0x0000000000400b05 <+21>: jmpq 0x4008f0 <puts@plt>
End of assembler dump.
(gdb) disass thread_fun2
Dump of assembler code for function _Z11thread_fun2v:
0x0000000000400b10 <+0>: mov $0x40109d,%edi
0x0000000000400b15 <+5>: movl $0x3,0x201571(%rip) # 0x602090 <a>
0x0000000000400b1f <+15>: jmpq 0x4008f0 <puts@plt>
End of assembler dump.
(gdb)

测试输出

[root@centos-test tmp]# ./multi 
Set!
^C
[root@centos-test tmp]# ./multi
Set!
^C
[root@centos-test tmp]# ./multi
Set!
^C
[root@centos-test tmp]# ./multi
Set!
^C
[root@centos-test tmp]# ./multi
Set!
^C

更新: 谢谢大家,现在我发现这个问题实际上是由编译器引起的。

(gdb) disass thread_fun
Dump of assembler code for function _Z10thread_funv:
0x0000000000400af0 <+0>: cmpl $0x3,0x201599(%rip) # 0x602090 <a>
0x0000000000400af7 <+7>: je 0x400b00 <_Z10thread_funv+16>
0x0000000000400af9 <+9>: jmp 0x400af9 <_Z10thread_funv+9> ###jump to itself
0x0000000000400afb <+11>: nopl 0x0(%rax,%rax,1)
0x0000000000400b00 <+16>: mov $0x401090,%edi
0x0000000000400b05 <+21>: jmpq 0x4008f0 <puts@plt>
End of assembler dump.

编译器似乎将其视为单线程应用程序。

最佳答案

问题是标准说允许编译器优化你的代码,如果它没有数据竞争(不是直接引用!)。

所以当它分析的时候

while(a!=3) {

}

它发现它需要检查 a!=3直到下次重复循环时才会发生任何事情,因此无需检查 a又一次,因为它不可能改变。

因此将 a 的类型更改为 std::atomic<int>将强制它检查 a 的值再次循环,循环应该按预期工作。

关于linux - 为什么下面的代码无法输出 Hello World?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53664178/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com