![]() | 1 lcdtyph 2024-05-15 12:18:18 +08:00 via iPhone ![]() 在 x86_64 架构上: 变量地址对齐的情况下,atomic read/write 确实就是一条 mov 指令 但是 atomic 包应该还会额外提供插入 mfence 来阻止指令 store-load 重排的问题 |
![]() | 2 coyove 2024-05-15 12:43:59 +08:00 请搜 memory order |
![]() | 3 ysc3839 2024-05-15 12:50:29 +08:00 via Android “也就是说对一个 int32 进行读写,本身即可满足第一条要求” 否的,要考虑对齐情况 |
![]() | 4 PTLin 2024-05-15 13:58:31 +08:00 给你补充下,go 我不太清楚,Linux 内核的原子变量的 api 还有个功能就是防止操作被编译器优化。 假设一个循环(无内存屏障,同步原语情况下)里有 a = b ,编译器有可能把这句优化到循环之外,因为编译器的角度这句话运行一次和运行多次无异,但是我们知道 b 是被多个执行流共享的变量,所以需要使用 api 防止操作被优化。 |
![]() | 5 MoYi123 2024-05-15 14:09:49 +08:00 内存可见性, 指令重排都不能保证 |
![]() | 6 Orlion 2024-05-15 14:24:22 +08:00 ![]() 在 x86_64 上 atomic.LoadInt32 实际源码就是直接取数据,对应源码如下: ``` func Load(ptr *uint32) uint32 { return *ptr } ``` 而 WriteInt32 有所不同,其中使用了 XCHGL ,这个指令有 LOCK 指令前缀的效果,可以保证可见性。 ``` TEXT Store(SB), NOSPLIT, $0-12 MOVQ ptr+0(FP), BX MOVL val+8(FP), AX XCHGL AX, 0(BX) RET ``` 因此在 x86_64 平台上不使用 atomic 包也能保证原子性,但是保证不了可见性,如果程序中对可见性没有要求,以我的认知我觉得可以不使用 atomic 包,话虽如此实际工作中并发场景中该加还是加吧,说不准认知之外还有什么别的坑呢? btw ,多年前我对这个问题也有过一段时间疑问与探索,整理了一篇博客: https://blog.fanscore.cn/a/34/ 可以参考一下。 |
7 GeruzoniAnsasu 2024-05-15 14:27:15 +08:00 请参考 c++ 的 memory order: https://zh.cppreference.com/w/cpp/atomic/memory_order 这堆内存序的说明可以帮助你理解为什么要有专门的原子操作函数 |
![]() | 8 lance6716 2024-05-15 18:42:53 +08:00 via Android 官方文档有说明,go 内存模型符合 drf-sc ,所以写程序符合 data race free 的约定就没啥问题 |