它是什么

内存模型是用来描述多线程程序中,不同线程之间共享内存的方式和规范。

为什么需要它

在多核、多线程的计算机系统中,同一块内存(即临界区)可能被多个线程同时访问,如果不加以规范,在许多情况下会导致程序出错。内存模型的出现就是为了解决多线程下程序的正确性问题。

它规定了什么东西

对于一般的编程语言而言,在讨论内存模型时,本质上是在讨论如下三个方面的问题:

  • 原子性
  • 内存屏障
  • 内存重排序

原子性

很好理解,即一个操作要么全部完成,要么不完成。基本有多线程能力的编程语言都会提供如atomic add, atomic set 等操作

内存屏障

内存屏障可以通过CPU指令级别的方式来保证内存操作的原子性和顺序性,确保线程的数据修改在内存中是有序的,避免多个线程同时修改同一块内存导致数据混乱的情况发生。它可以划分为两种类型:读屏障和写屏障。

  1. 读屏障用于确保在执行某个操作之前,内存中的数据已经被加载到寄存器中,保证读取到的是最新的数据。

  2. 写屏障用于确保在执行某个操作之后,寄存器中的数据已经被刷新回内存中,保证修改后的数据对其他线程可见。

内存屏障原理

内存屏障的原理是通过CPU添加特殊的指令来实现的。这些指令在执行时会强制CPU暂停一段时间,以确保其前面和后面的内存访问发生的顺序与代码编写时的顺序一致。这样可以防止多线程程序出现数据异常的情况。

具体来说,内存屏障的原理包括2个方面:

  1. 内存同步指令:内存同步指令包括内存屏障和锁定。内存屏障通过添加特殊的机器指令到CPU中来实现内存同步,其作用是让编译器和处理器在读写内存时,避免可能出现的指令重排、乱序执行等问题。

  2. 内存一致性协议:内存一致性协议保证了多个CPU之间共享的内存数据的一致性,当一个CPU修改了共享内存中的某个数据时,其他CPU能迅速地看到并更新本地缓存中的数据。

总之,内存屏障的原理是通过CPU添加特殊的指令,来保证线程对共享内存的读写顺序和同步。这样可以避免多线程程序出现数据竞争和错误,保证程序的正确性和性能。

内存重排序

内存重排序是指编译器和CPU为了优化程序而对指令进行的重新排序。在某些情况下,这种重排序可能会破坏程序的正确性。所以一般的编程语言的内存模型都会规定了一些内存重排序的规则,以避免程序出错。

展开讲讲内存一致性协议

内存一致性协议是指多处理器间共享内存数据的一致性保证机制,保证了多个处理器之间共享的内存数据的一致性。内存一致性协议通常包含如下几个基本原则:

  1. 共享内存的数据一致性:处理器之间共享内存的数据需要保证一致性。
  2. 处理器之间的通信:每个处理器必须能够检查其他处理器的缓存中是否已经存在内存数据。
  3. 数据的变化:处理器修改缓存中的数据时必须通知其他处理器缓存中该数据的状态已经过期,需要重新从主存中读取。
  4. 内存的访问速度:为了保证访问速度,内存一致性协议需要尽可能减少处理器之间的通信频率。

在多处理器系统中,各处理器访问共享内存时,会首先在自己的缓存中查找该内存位置的数据。如果该数据已被缓存,则处理器就从缓存中获取该数据。如果缓存中没有找到该数据,则需要从内存中读取数据。当处理器修改缓存中的共享数据时,内存一致性协议的机制就会保证其他处理器能够感知到数据的变化,并进行相应的更新。

总之,内存一致性协议是多处理器系统中的一种内存保证机制,保证多个处理器之间共享的内存数据的正确性和一致性。它可以有效避免由于多个处理器对同一块共享内存进行操作而产生的一系列问题。