什么是内存模型(Memory Consistency Model)
最近在看 《C++ Concurrency in Action》第五章C++内存模型的时候,对于其中提到的一些知识点有点理解困难。所以另外找了一些资料先了解一些什么是内存模型,先对与内存模型有一个整体的概念然后再深入去了解C++的内存模型。
什么是内存模型
In computing, a memory model describes the interactions of threads through memory and their shared use of the data.
Wikipedia
有点抽象,似乎还是没有很好地定义出内存模型是什么,下面这段是摘自A Primer on Memory Consistency and Cache Coherence(APMCCC)1第三章。
A memory consistency model, or, more simply, a memory model, is a specification of the allowed behavior of multithreaded programs executing with shared memory. For a multithreaded program executing with specific input data, it specifies what values dynamic loads may return and what the final state of memory is.
简单的说,内存模型可以理解为一套协议,定义多个处理器/线程在在操作内存的时候需要遵循的一套协议。什么是允许的什么是不允许的。
可以看到这里的内存模型和内存一致性模型指的是同一个概念。
内存一致性模型的很多概念可以推广到一致性模型,一致性模型则是在分布式系统中很重要的一个概念。从某一个角度来说,多(核)处理器与内存的关系也是一种分布式系统。
内存模型的分类
内存模型可以分为硬件内存模型(hardware memory model)和软件内存模型(software memory model) 3。
硬件内存模型可以理解为硬件与软件之间的一套协议(contract between the hardware and software) 2,硬件会在协议中说明会在什么情况下进行重排什么情况下不会。这里的硬件一般指的是处理器,而软件指的是操作处理器的指令。
软件内存模型可以理解为程序员和编程语言之间的一套协议(contract between programmer and programming language),编程语言会规定一套规则来说明什么情况下会对代码进行重排,并且提供一些机制能够让程序员对一些操作进行控制。
从硬件和软件的角度是看内存模型的一个维度,另一个维度则是一致性的强度。一致性可以是强一致性也可以是弱一致性。
这张不严谨的图参考自Weak vs. Strong Memory Models,稍微做了一下变换。
大部分程序员关心的是软件维度的内存模型,即程序员和编程语言之间的协议。内存模型的强度与软硬件无管,是抽象层面的一个东西即适用于硬件也适用于软件。
在wikipedia上我们可以看到有很多不同的一致性模型分类,这里对于C++中的内存模型比较相关的是:Sequential Consistency、Release consistency。
Sequential Consistency
Sequential Consistency(SC)是最符合直觉的一种内存模型也是很关键的一种。是由Leslie Lamport在1979年提出来的。
理解这个模型有两个关键点:
- 程序的执行顺序按照代码顺序
- 代码中对于内存的访问不会被乱序
#1 很好理解,即执行顺序不会随意重排,尊重代码顺序。#2则不是很好实现,
上图为APMCCC中的截图。把内存操作想象成都需要通过一个开关,每次内存都挑选一个核允许其进行内存访问。这样就可以保证所有的内存访问不会被乱序。不难发现这个模型最大的问题就是同一时间只能有一个核对内存进行访问,这个很大程度上削弱了多核带来的提升。
Release consistency
在Release consistency中进入critical section(关键区)称为acquire,离开critical section称为release。Acquire操作是读操作,release是写操作。
简单的理解就是acquire操作会阻止所有在此操作以下的内存读取操作被重排到此操作前。release会保证所有操作之前的内存读取操作不会被重排到release操作后。下图可以很清晰的表达这个关系(The Purpose of memory_order_consume in C++11):
总结
对于理解C++的内存模型,上面的这些预备知识就差不多足够了。强烈推荐阅读Preshing关于Lock-free的一系列博客,还有这本小书A Primer on Memory Consistency and Cache Coherence。
Preshing的Lock-free的系列博客,没有列全,可以顺藤摸瓜找到相关文章。
- Memory Barriers Are Like Source Control Operations
- Weak vs. Strong Memory Models
- Acquire and Release Semantics
- The Purpose of memory_order_consume in C++11