理解原子变量之三:原子性与memory_order_relaxed
目录
CPU与内存的关系
原子性
典型使用场景
在本系列的第一篇文章理解原子变量之一:从互斥锁到原子变量,最粗浅的认识_原子互斥-CSDN博客,我通过几个实例从感性认识的角度介绍了原子性。本文在第一篇文章的基础上,从理性认识的角度进一步讲述原子性的含义。下一篇文章将详细描述可见性。
CPU与内存的关系
现代的CPU一般都是多核(core)CPU,CPU与内存的关系如下图所示。下面的图来自大白话C++之:一文搞懂C++多线程内存模型(Memory Order)_c++ memory order-CSDN博客
原子性
可见,CPU通常不会直接对主内存(RAM)进行读写,因为CPU的核(core)与RAM之间隔了几级的缓存(cache),以及寄存器。
假如内存里有一个变量a,cpu给该变量+1的过程可能是这样的:先把新的值写入cache,然后把cache的内容写入ram。可见,这个写入过程可能不是一步完成的。假如在这个过程里,另一个cpu的core也要操作a++,那么两个线程之间就可能发生访问冲突。理想情况下,既然两个线程分别要给a+1,那么最后a的结果应该+2才对。但是最后a的结果可能没有+2,而是仅仅+1.这便是对原子性的破坏。
在std::memory_order - cppreference.com有一段对memory_order_relaxed功能的描述:
仅对此操作要求原子性。
这里,任何遵守原子性的操作,都保证本操作是不可分割的,即在执行遵守原子性的操作,不能被在中途被其他操作插入干预。这也是std::memory_order的6个内存序都必须满足的要求,当然也就是原子操作的最低要求。
在前一篇文章理解原子变量之二:从volatile到内存序-进一步的认识-CSDN博客里,我提到了原子变量的功能分为三部分:原子性、可见性和限制指令重排。memory_order_relaxed仅具备原子性,不保证可见性和限制指令重排,所以它是6种内存序里面最弱的内存序。
典型使用场景
store操作与fetch_add操作是运用memory_order_relaxed的典型场景。既然fetch_add遵守memory_order_relaxed次序,则取数据,再加上,然后储存回去就是一套不可分割的连贯动作。见std::memory_order - cppreference.com
下一篇文章将结合另外两个内存序memory_order_acquire与 memory_order_release描述可见性。
