From 377700d6cc9be0289eece7abea5debc3074b0cd6 Mon Sep 17 00:00:00 2001 From: marsonshine Date: Mon, 13 May 2024 18:38:35 +0800 Subject: [PATCH] doc: memory barrier; --- WHPerformanceDotNet/docs/MemoryModel.md | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/WHPerformanceDotNet/docs/MemoryModel.md b/WHPerformanceDotNet/docs/MemoryModel.md index 56eb13c..7e022f5 100644 --- a/WHPerformanceDotNet/docs/MemoryModel.md +++ b/WHPerformanceDotNet/docs/MemoryModel.md @@ -15,6 +15,36 @@ 不同处理器架构对程序编码也有明显影响,特别是当在线程同步的某些 bug 情况下。因为在 ARM 下,JIT 编译器要比在 x86/x64 下对读写指令的重排序更加自由,所以关于线程同步的 bug 在后者可能无法察觉,但是转到 ARM 下就能看到。 +## 内存屏障 + +屏障(Memory Barrier)是一种同步机制,用于控制指令重排序和内存访问顺序,确保指定操作的执行顺序以及内存操作的可见性。主要有以下几种类型 + +### 写屏障 + +确保在屏障之后的任何写操作都不会对其他 CPU 可见,直到屏障之前的所有写操作对其他 CPU 可见。即:确保屏障前的写操作在屏障后的任何写操作之前完成。 + +### 读屏障 + +确保在屏障之后的任何读操作都不会被重排序到屏障之前。即:确保屏障前的读操作在屏障后的任何读操作之前完成。 + +### 通用内存屏障 + +也叫全屏障,结合读屏障和写屏障的功能,保证所有先前的读写操作在通用屏障的后续操作之前完成。它们是实现线程同步、锁等同步原语的基础。 + +### 数据依赖屏障 + +数据依赖屏障是一种用于处理指令间明确**数据依赖关系**的同步机制。这种依赖通常出现在当一个操作的输出直接作为另一个操作的输入时。数据依赖屏障确保在有数据依赖的两个操作之间,第一个操作的结果必须在第二个操作开始前完全可用。这对于确保程序在多处理器系统中按预期执行非常关键,特别是在使用弱内存模型的处理器架构中。 + +例如,在以下情况需要数据依赖屏障: + +- 在加载一个变量的值后,基于这个值进行一些计算或决策。数据依赖屏障会确保加载操作完成,且其结果对接下来的操作可见。 + +### 控制依赖屏障 + +控制依赖屏障用于处理**程序控制流中的依赖**。控制依赖发生在程序的执行路径依赖于某些条件判断的结果。控制依赖屏障确保在进行决策前,所有相关的条件检查都已完全评估完成,并且其结果正确地影响了程序的控制流。 + +例如:在判断指令(如`if`语句)中使用了某个变量的值,而这个变量可能由其他 CPU 核心在并行修改。而没有控制依赖屏障的情况下,处理器或编译器可能会提前读取这个变量的值,导致产生错误的执行路径。而控制依赖屏障就是确保在执行决策逻辑前,所有相关的数据加载操作已经完成,并且结果已经是最新的。 + ## volatile 关键字 Volatile 就是设置系统编译器是否对这些读写指令进行重新排序,加上 Volatile 关键字就是表明要严格按照顺序执行指令。