【C# 线程】内存模型(C#)---非常重要 【多线程、并发、异步的基础知识】
阅读原文时间:2023年07月10日阅读:1

MSDN:理论与实践中的 C# 内存模型

MSDN:理论与实践中的 C# 内存模型,第 2 部分

内存模型就是内存一致性模型。

以下内如来自维基百科

  • 线性一致性(Linearizability)或严格一致性(Strict consistency):任何对一个内存位置X的读操作,将返回最近一次对该内存位置的写操作所写入的值。
  • 原子一致性(Atomic consistency):读操作未能立即读到此前最近一次写操作的结果,但多读几次还是获得了正确结果。所有对数据的修改操作都是原子的,不会产生竞态冲突
  • 顺序一致性(Sequential consistency ):(并发程序在多处理器上的)任何一次执行结果都相同,就像所有处理器的操作按照某个顺序执行,各个微处理器的操作按照其程序指定的顺序进行。换句话说,所有的处理器以相同的顺序看到所有的修改。读操作未必能及时得到此前其他处理器对同一数据的写更新。但是各处理器读到的该数据的不同值的顺序是一致的。
  • 缓存一致性(Cache Coherence)
  • 静态一致性(Quiescent consistency)
  • 处理器一致性(Processor consistency)/PRAM一致性(PRAM consistency,P指pipeline):在一个处理器上完成的所有写操作,将会被以它实际发生的顺序通知给所有其它的处理器;但是在不同处理器上完成的写操作也许会被其它处理器以不同于实际执行的顺序所看到。这反映了网络中不同节点的延迟可能是不相同的。对于双处理器,处理器一致性与顺序一致性是等价的。
  • 释放一致性(Release consistency ):在对一个共享变量进行普通访问之前,进程在之前所有的获得锁而进行的操作必须成功的完成。在释放一个锁操作之前,进程之前的读和写操作必须已经完成。获得和释放锁的操作必须符合“FIFO一致性”。“释放一致性”仅仅关注被锁住的共享内存内存变量,仅仅只需要将对被锁住的共享变量的修改通知给其它的处理器。C#的VolatileWrite函数即实现了释放一致性语义。
  • 因果一致性(Causal consistency )
  • TSO一致性(Total store ordering)
  • PSO一致性(Partial store ordering)
  • 弱序一致性(Weak-ordering consistency)
  • 最终一致性(Eventual consistency)

C# 内存模型是一组规则,描述允许和不允许的内存操作重新排序类型。 所有程序都应该根据在规范中定义的保证进行编写。

大部分的规则由编译器执行,少部分规则对对程序员开发,例如内存重排序,C#提供了volatile关键字和内存屏障,让程序员控制内存的排序。

C# 内存模型允许在某一方法中对内存操作进行重新排序,只要单线程执行的行为不发生改变即可。
但是,即使允许编译器(JIT)和处理器(CPU)对内存操作进行重新排序,也不意味着它们在实际情况下会始终这样做。
根据这个抽象 C# 内存模型而包含“错误”的许多程序仍会在运行特定版本 .NET Framework 的特定硬件上正确执行。
值得注意的是,x86 和 x64 处理器仅在某些范围较窄的方案中对操作重新排序;
同样,CLR 实时 (JIT) 编译器不会执行所允许的许多转换。
尽管您在编写新代码时应该对这个抽象的 C# 内存模型已心中有数,但理解这个内存模型在不同体系结构上的实际实现方式是很有用的,特别是在尝试理解现有代码的行为时。

主要针对的对象是编译器(JIT)和处理器(CPU)对内存代码重新排序,原子性访问。

备注:原子性代码:如果一组变量总是在相同的锁内进行读写,就可以称为原子的(atomically)读写。假定字段xy总是在对locker对象的lock内进行读取与赋值;a++就不是原子性代码

x86-TSO模型的特点总结:

  因为缓存有MESI协议保证一致性,所以缓存可以和主存合并抽象成共享存储

  x86-TSO的写操作严格遵循FIFO

  CPU流水线式地执行指令会使得CPU对接受到的指令流顺序执行

  x86-TSO中唯一重排的地方在于StoreBuffer,因为StoreBuffer的存在,核心的写入操作被缓存,无法马上刷新到共享存储中被其他核心观察到,所以就有了 “ 写 ” 比 “读” 晚执行的直观感受,也可以说是读操作提前了,排到了写操作前

  阻止这种重排的方法是 使用带 lock 前缀的指令或者XCHG指令,或MFENCE指令,将StoreBuffer中的内容刷入到共享存储,以便被其他核心观察到 store-load 编程优化成load-store