C++11中的原子量和内存序详解

2020-01-06 19:27:01于海丽

显然,由于自增操作各个步骤的交叉执行,导致最后我们得到一个错误的结果。

原子量可以解决i++问题,那么可以解决指令重排的问题吗?也是可以的,和原子量选择的内存序有关,我们把这个问题放到下一节专门研究。

上面已经看到atomic是一个模版,那么也就意味着我们可以把自定义类型变成原子变量。但是是否任意类型都可以定义为原子类型呢?当然不是,cppreference中的描述是必须为TriviallyCopyable类型。这个连接为TriviallyCopyable的详细定义:

http://www.easck.com/w/cpp/concept/TriviallyCopyable

一个比较简单的判断标准就是这个类型可以用std::memcpy按位复制,例如下面的类:


class {
 int x;
 int y;
}

这个类是一个TriviallyCopyable类型,然而如果给它加上一个虚函数:


class {
 int x;
 int y;
 virtual int add ()
 {
  return x + y;
 }
}

这个类便不能按位拷贝了,不满足条件,不能进行原子化。

如果一个类型能够满足atomic模版的要求,可以原子化,它就不用进行加锁操作了,因而速度更快吗?依然不是,atomic有一个成员函数is_lock_free,这个成员函数可以告诉我们到底这个类型的原子量是使用了原子CPU指令实现了无锁化,还是依然使用的加锁的方式来实现原子操作。不过不管是否用锁来实现,atomic的使用方式和表现出的语义都是没有区别的。具体用哪种方式实现C++标准并没有做约束(除了std::atomic_flag特化要求必须为lock free),跟平台有关。