注意:不是这个问题的重复。
假设某个内存区域永远不会被读取,那么并发非原子写入什么时候对它来说是安全的?这与语言无关,主要与 CPU 架构限制有关。
这个想法是为了在多线程应用程序中删除不可查找的对象(例如 TCP 套接字)中的字节,但在 BPF 删除过滤器不可行的情况下。
read
系统调用以完全接收所有接收到的数据)并且还没有遇到问题到目前为止。缓存在所有 CPU ISA(不一定是 GPU)上是一致的,至少在我们运行线程的核心之间是一致的,这就是为什么 C / C++
volatile
与 atomic<T>
与
memory_order_relaxed
的工作原理类似,在普通编译器上将 volatile
访问视为需要在 asm 中加载或存储。 (何时在多线程中使用 易失性? - 永远不会,除了在 Linux 内核代码中,它使用内联 asm 滚动自己的原子进行排序,以及 volatile
的 GNU C 语义,其中包括使用单个指令进行加载或存储如果可能的话。)
因此,对于 CPU 内核要将其私有存储缓冲区中的存储提交到一致的 L1d 缓存中,它需要在提交之前获得其存储到的缓存行的 MESI 独占所有权。用 C++ 术语来说,这就是为什么所有 atomic
变量都存在“修改顺序”的原因。在 asm 中,每个缓存行都存在这样的顺序。
如果您的 ARM 板带有微控制器 + DSP 和非一致性共享内存,您仍然可以将两个内核存储到同一地址,而不会出现任何问题,除非您读取该共享内存区域,否则可能会获得令人惊讶的值。例如带有缓存的核心可能会看到它最后存储的值,即使另一个核心已经完成了稍后的存储。
在高级语言中,通常不安全地假设使用非原子赋值的代码编译为与atomic
relaxed
等效的 asm,除非您在处理的主流编译器上使用类似 C volatile
的东西正如您所期望的那样。
clang -fsanitize=thread
这样的C实现上,当两个线程同时写入相同的非原子stderr
时,它可能会中止或打印额外的内容到int *
。
我不知道你在说什么write
系统调用;这似乎与 asm 存储关系很远,并且内核需要实现 POSIX 语义以实现write
原子性(文件位置和 I/O 的原子更新,以防多个进程或线程共享相同的打开文件描述符.)请参阅https://man7.org/linux/man-pages/man2/write.2.html#BUGS了解一些相关内容,例如Linux 3.14 及更高版本正确实现了这一点。
TLB 在这里不相关。