为何x86平台下该程序的两个assert均可通过?(基于C++/Rust内存模型)
为什么x86平台上两个assert均可通过?
首先要明确两个核心点:x86的TSO(Total Store Order)内存模型,以及独立缓存行的异步刷新行为。
关键细节拆解
存储缓冲区与异步刷新
x86每个核心都有自己的存储缓冲区,线程执行写操作时,会先将值写入缓冲区,之后再异步刷新到L1缓存(这个刷新过程没有严格的全局同步时序):- 线程1的
x = true(release语义)会先进入线程1核心的存储缓冲区,之后异步刷入缓存; - 线程2的
y = true(release语义)同理,进入线程2核心的存储缓冲区后异步刷入缓存。
- 线程1的
缓存一致性的“最终”而非“实时”
x86是缓存一致架构,但这个一致性是最终一致——保证所有核心最终会看到相同的变量值,但不保证某个核心的写操作会被其他核心“实时”观测到。此外,x和y属于独立的缓存行,它们的刷新操作完全并行、无依赖关系。两个assert通过的场景
- 线程3执行
assert(x && !y)时:先读取x,此时线程1的x=true刚好已刷入缓存,线程3看到x=true;接着读取y,线程2的y=true还在存储缓冲区未刷新,所以看到y=false,assert通过。 - 线程4执行
assert(!x && y)时:先读取y,此时线程2的y=true刚好已刷入缓存,线程4看到y=true;接着读取x,线程1的x=true还在存储缓冲区未刷新,所以看到x=false,assert通过。
- 线程3执行
纠正你的误区
你认为“assert(x && !y)通过则写入x的核已清空存储缓冲区”是不准确的:线程3看到x=true仅意味着x的写操作已从线程1的存储缓冲区刷入缓存,但线程2的y写操作完全独立,它的存储缓冲区是否刷新和x的状态无关。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

