老哥们请教个基础问题, c/c++ 对基础数据类型的赋值是原子操作吗?

2023-08-28 18:07:25 +08:00
 CrazyRain0001

前景提要

之前我写代码同步多线程访问时,基础数据类型都加的有 atomic 关键字,后来领导看到了说基础数据类型不加也是原子操作。 今天面试时,面试官说基数数据类型访问不是原子的,而且和编译器架构无关。

我的理解

应该加 atomic 关键字,但在现代 x86 等架构的 cpu 上对 bool ,int 类型的操作是原子的,或者说视同原子的。

1235 次点击
所在节点    问与答
18 条回复
xtreme1
2023-08-28 18:14:41 +08:00
mtrec
2023-08-28 18:15:13 +08:00
面试官是对的 atomic 之后是原子的 里面还涉及更深一层的 memory order

“在现代 x86 等架构的 cpu 上对 bool ,int 类型的操作是原子的,或者说视同原子的”
不对 在多核多线程情况下 每个核都有自己的独占的寄存器/L1/L2 cache 不能保证原子性
billlee
2023-08-28 18:18:48 +08:00
是原子的,原子意味着着写一个 memory word 不会出现高位写入完成,而低位没完成写入的情况
inhzus
2023-08-28 18:33:57 +08:00
不用 atomic 有可见性问题
ajaxgoldfish
2023-08-28 23:37:52 +08:00
我记得有本书讲的是和 CPU 的位数有关,还和是否为浮点数有关。其中在某些条件下是原子的,超过限定条件就有可能不是原子的。虽然记得不清楚但是应该能否定面试官说的
hanguofu
2023-08-29 01:53:02 +08:00
取决于硬件是否支持?
shawnsh
2023-08-29 09:02:58 +08:00
怎么牵扯到编译器的架构了
CrazyRain0001
2023-08-29 10:33:00 +08:00
@shawnsh 写漏了,编译器优化和 cpu 架构
CrazyRain0001
2023-08-29 10:33:23 +08:00
@inhzus 对,这点同意
CrazyRain0001
2023-08-29 10:54:37 +08:00
@xtreme1 看文档我的理解是做了内存一致性保证的?
https://img.cxlljj.top/images/2023/08/29/image.png
CrazyRain0001
2023-08-29 10:56:36 +08:00
@mtrec 我看这边祖传代码一直是直接用的,不能保证的话不是很容易崩吗?
sghwn2
2023-08-29 11:16:34 +08:00
@mtrec 那如果加了 volatile 可以吗
Caturra
2023-08-29 11:31:02 +08:00
你让面试官翻译翻译这段话

8.1.1 Guaranteed Atomic Operations

The Intel486 processor (and newer processors since) guarantees that the following basic memory operations will always be carried out atomically:
- Reading or writing a byte
- Reading or writing a word aligned on a 16-bit boundary
- Reading or writing a doubleword aligned on a 32-bit boundary

The Pentium processor (and newer processors since) guarantees that the following additional memory operations will always be carried out atomically:
- Reading or writing a quadword aligned on a 64-bit boundary
- 16-bit accesses to uncached memory locations that fit within a 32-bit data bus

The P6 family processors (and newer processors since) guarantee that the following additional memory operation will always be carried out atomically:
- Unaligned 16-, 32-, and 64-bit accesses to cached memory that fit within a cache line
mtrec
2023-08-29 12:14:10 +08:00
@sghwn2 加了 volatile 也不行 volatile 是提醒编译器别优化 可能别的地方也会改这个变量 每次用到的话从内存里重新取值 但是还是没解决多线程下可能的编译器 CPU 指令重排 memory order 能提供更精细的重排控制
mtrec
2023-08-29 12:16:21 +08:00
@CrazyRain0001 我不了解你那边代码的情况无法回答你 建议你可以看看 std atomic 相关的内容 cppcon 有一期就是解释这个原理的
CrazyRain0001
2023-08-29 14:36:54 +08:00
@mtrec
> 是这个吗? https://www.bilibili.com/video/BV1Vx411V7Rd/?p=31
简单看了下,他确实指出了代码里对类似 int i 的基础操作是非原子的,包含了不同的 CPU 指令。但看 13 楼引用的这个 intel 开发文档也确实说明了某些 CPU 对于 bool(byte)或者 int(doubleword aligned on a 32-bit boundary)的读写是原子操作 Certain basic memory transactions (such as reading
or writing a byte in system memory),所以可以认为这是一个语言层面未作保证只是某些 CPU 支持的特性吗?
mtrec
2023-08-29 18:59:28 +08:00
@CrazyRain0001 对 是这些视频 这个跟 13 楼讲的不冲突 就用 cppcon 里两个线程跑++i 的例子 CPU 可以保证两次都原子性的从内存读到 i 的值 然后分别一步步写到两个线程各自的 L2/L1 cache 和寄存器里 两个自增也能在 1 tick 完成 原子性的 然后再一步步地 commit 回 L3 再内存 就可能出现覆盖而得不到你想要结果 因为两个线程没有同步机制 而 std atomic 相当于一种硬件同步机制或者硬件锁 底层是通过 CPU 指令来实现的 现在在 ARM 或者 GPU 上支持还不算完善 这些 atomic 操作也是很多 lock free 数据结构的基础
CrazyRain0001
2023-08-30 10:37:09 +08:00
@mtrec #17 好的!感谢回答!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/968964

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX