文章目录
- 一、C++ 内存模型
- 1、为什么需要内存模型?
前言
C++ 11标准中最重要的特性之一,是大多数程序员都不会关注的东西。它并不是新的语法特性,也不是新的类库功能,而是新的多线程感知内存模型。本文介绍的内存模型是指多线程编程方面,而非对象的内存布局与内存对齐之类。
一、C++ 内存模型
1、为什么需要内存模型?
要回答这个问题需要从CPU架构说起,下面是一个的多核CPU架构图,如下:
- Core:每个Core独享SB与L1
- SB(Store Buffer):Store Buffer是一个缓冲区,用于暂存CPU的写操作,它允许CPU把数据先写入Store Buffer,然后继续执行其他操作,而不是等待数据被写入缓存或内存后再进行下一步。这样设计的好处是显著降低了内存写延迟对CPU性能的影响。
- L1 Cache:存储了CPU近期可能访问的数据和指令,且两个L1 Cache独享一个L2 Cache
注意:上面的CPU架构只是部分CPU采用的架构,并不能代表全部。
为什么需要使用Cache?
如果没有Cache,CPU每执行一条指令就要到内存中取数据。执行一条指令只需要几个时钟周期,而取指令需要上百个时钟周期,这就将导致CPU大部分时间都处于等待状态,进而导致执行效率低下,引入了Cache主要解决CPU等待问题。
使用Cache会引入一些新的问题,例如:Cache的一致性、Cache的缺失等,为了解决这些问题,各CPU平台(ARM/X86/IA64)都有自己的解决方案。软件层面(编译器)也会有对应的优化,这导致了CPU执行的程序并不是你写的那个版本,只是从结果上看不出差异而已。
编译器和CPU优化都遵循了一个同样的原则,即优化后的代码若是单线程执行,要与原有代码行为保持一致;再加之多线程环境我们使用的互斥锁,其对编译器与CPU优化做了很多限制,可以让我们对线程间的执行顺序进行同步,进而保证即使被优化成了另一个程序,仍然有相同的执行结果。
若是我们从比互斥锁更为底层地去了解线程间的同步机制,我们势必会看到CPU平台(ARM/X86)和编译器的差异,进而可以知道优化的存在。现代C++的内存模型,便是为了屏蔽这些差异,而让你可以不用去了解特定平台特定编译器,也不用依赖互斥锁,从更为底层的层面,就可以完成线程间的同步。C++ 11开始提供的
std::atomic
模版,便可以作为更为底层的同步工具,这也是内存模型起作用的地方。