c++11 多线程 顺序执行_【工程经验系列】c++11与内存模型

在多核CPU时代,多线程成为一种更高效的编程方式,为了更好的利用多线程编程,我们有必要了解和学习linux内存模型。

1 Linux中的cache

讲cache之前,简单了解一下程序是怎么在机器运行的, linux环境下程序是运行在 RAM之中(默认都知道啊),RAM 就是所谓的DDR,称之为main memory(主存)。当我们在Linux环境下启动一个线程时,操作系统会进行调度,从磁盘中将可执行文件加载到主存中,然后开始运行程序,这个运行过程中会涉及到主存和CPU之间交互,为了方便叙述,我们用一个简单的例子说明这个程序执行过程,代码如下:

int a=0;a=a+1;

如果CPU需要将一个变量a(因为实际是内存操作,我们假设地址是A啊)加1,一般分为以下3个步骤:

  1. CPU 从主存中读取地址A的数据到内部通用寄存器 x0。
  2. 通用寄存器 x0 加1。
  3. CPU 将通用寄存器 x0 的值写入主存。

整个过程如下图所示:f2187fee6fb22d1e12d2c2337488d7a9.png

图1

上图显示的只是一个理想过程,理想是丰满的,但是现实是骨感的啊,其实现实中,CPU通用寄存器的速度和主存之间存在着太大的差异。两者之间的速度差距很大,CPU register的速度一般小于1ns,主存的速度一般是65ns左右。速度差异近百倍啊。因此,上面举例的3个步骤中,步骤1和步骤3实际上速度很慢。当CPU试图从主存中load/store 操作时,由于主存的速度限制,CPU不得不等待这漫长的65ns时间。所以为了提升处理效率,我们有必要提升主存的速度,出于成本和效率考虑,人们考虑在cpu与主存之间加入缓存在硬件上,我们将cache放置在CPU和主存之间,作为主存数据的缓存。当CPU试图从主存中load/store数据的时候, CPU会首先从cache中查找对应地址的数据是否缓存在cache中。如果数据缓存在cache中,直接从cache中拿到数据并返回给CPU。当存在cache的时候,程序运行流程如下:369246933be898414cfb9b2d359a0a59.png

图2

有没有感觉redis就是和这玩意差不多呢,事实上cache的花样很多,上图只是一个简单模式,事实上现代多核CPU都长成下图这样:dfba943844d473dcc6de47f6fa7b7595.png

图3

但是,这就满足人们对性能的追求了吗?并没有。为了进一步提升性能,引入多级cache。前面提到的cache,称之为L1 cache(第一级cache)。我们在L1 cache 后面连接L2 cache,在L2 cache 和主存之间连接L3 cache。等级越高,速度越慢,容量越大,每个CPU也都有自己内部才能访问的缓存,结构变成了图3所示的这个样子啊,执行如下:

  • 有多个CPU处理器,每个CPU处理器内部又有多个核心。
  • 存在只能被一个CPU核心访问的L1 cache。
  • 存在只能被一个CPU处理器的多个核心访问的L2 cache。
  • 存在能被所有CPU处理器都能访问到的L3 cache以及内存。
  • L1 cache、L2 cache、L3 cache的容量空间依次变大,但是访问速度依次变慢。

写到这你可能在想,这个缓存的结构和我们写c++代码有啥关系呢?我们考虑一种c++多线程的情况,不同的线程在不同核心运行时,这些缓存的存在会给数据同步带来挑战,当CPU结构发生变化,增加了只能由内部才能访问的缓存之后,一些在旧架构上不会出现的问题,在新的架构上就会出现。而本篇的主角内存模型(memory model),其作用就是规定了各种不同的访问共享内存的方式,不同的内存模型,既需要编译器的支持,也需要硬件CPU的支持。

2 从c++多线程访问数据开始

我们从一个c++多线程处理数据开始引入多线程数据同步问题:

#include#include #include #include  int A,B; void FuncA(){
         A=1;    std::cout<} void FuncB(){
         B=2;    std::cout<} int main(){
         A=0;    B=0;    std::thread thread1(FuncA);    std::thread thread2(FuncB);    thread1.join();    thread2.join();    return 0; }

上图的程序主要做了这样的实验,程序执行之前,A=B=0,有两个线程同时分别执行如下的代码:

线程1(thread1) 线程2(thread2)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值