为什么只有atomic_flag是保证无锁的

引言

在学习了C++中的原子操作后顿时感受到其贴近底层的强大,但是在学习的过程中还是有很多点并没有搞的十分的明白透彻,这篇文章的标题就是其中之一,在各大博客平台搜寻未果,在查阅了一些资料后对于这个问题有了一些理解 遂进行记录 对有同样疑惑的朋友提供一个参考方向
首先抛出问题,就是为什么在C++原子库中仅保证atomic_flag是保证无锁的,而atomic< int>,atomic< bool>不是呢

要解决这个问题我们首先来看看它们其中的结构 我们拿atomic< bool>和atomic_flag做个对比

//首先atomic_flag继承__atomic_flag_base
struct atomic_flag : public __atomic_flag_base {
...
}

//__atomic_flag_base的结构
struct __atomic_flag_base
{
  __atomic_flag_data_type _M_i;
};

//而__atomic_flag_data_type是这样的
#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1
    typedef bool __atomic_flag_data_type; 
#else
    typedef unsigned char __atomic_flag_data_type;
#endif
//我们可以看到atomic<bool>是atomic泛型的一个特化
template<>
struct atomic<bool>
{
private:
  __atomic_base<bool>	_M_base;
 ...
}

//我们再来看看_atomic_base<>
template<typename _ITp>
  struct __atomic_base
  {
  private:
    typedef _ITp 	__int_type;

    static constexpr int _S_alignment =
sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp);

    alignas(_S_alignment) __int_type _M_i;
    ...
  }

其实我们可以看到内部的存储其实都是bool类型,并没有什么区别

但是源码中有这样一段注释很有意思

  // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or
  // 8 bytes, since that is what GCC built-in functions for atomic
  // memory access expect.

其实就是说1,2,4,8个字节是编译器期望的值

下面是stackoverflow上对这个问题的高赞回答

  1. First of all, you are perfectly allowed to have something like std::atomic<very_nontrivial_large_structure>, so std::atomic as such cannot generally be guaranteed to be lock-free (although most specializations for trivial types like bool or int probably could,on most systems). But that is somewhat unrelated.

    首先 您被允许有std::atomic< 很大的且重要的结构>,
    所以这样的std::atomic通常不被保证是无锁的(在大多数系统上,尽管很多琐碎的数据类型例如bool,int等都是可以的(笔者:上面源码中的注释))

  2. No other type requires lock-free operations, and hence the atomic_flag type is the minimum hardware-implemented type needed to conform to this standard. The remaining types can be emulated with atomic_flag, though with less than ideal properties. In other words, it’s the minimum thing that must be guaranteed on every platform, so it’s possible to implement the standard correctly.
    没有其他类型需要无锁操作,因此atomic_flag类型是符合该标准的最小的硬件实现类型,剩下的类型可以用atomic_flag类型进行模仿,尽管其效率通常低于预想类型.换句话说,这是在每一个平台上必须被保证的最低要求,因此可以正确的实施该标准.

下面是知乎的回答

  1. 为什么atomic_flag是无锁的
    其实应该是反过来,std::atomic因为T的不确定所以无法做到一个可以应用到各种T的无锁实现,所以std::atomic就不能保证无锁。但是当T是bool或者int的时候就可以通过特定的cpu指令来保证操作在cpu的层面是atomic的。所以就有atomic_flag
  2. 为什么atomic< bool>不保证无锁呢
    因为atomic是范型的类,就是同样的逻辑应该在不同的T上。语言的标准上不能定义得这么细,atomic抽象出来就是提供原子性的功能,就不要求无锁了。当然我们实现的时候可以单独将T是bool和int的atomic特制化成无锁的,不过这样就不方便标准的指定,还不如引入另外新的概念来提供无锁的版本

结论

atomic< T>不保证无锁是因为防止T是一个很大的结构,其实atomic< T>在1,2,4,8个字节的都是很大可能保证无锁的,而atomic_flag是硬件的最低标准,保证无锁.

参考:
https://stackoverflow.com/questions/30256472/why-only-stdatomic-flag-is-guaranteed-to-be-lock-free

https://en.cppreference.com/w/cpp/atomic/atomic_flag

https://www.zhihu.com/question/366859588

https://mlog.club/article/2931718

发布了93 篇原创文章 · 获赞 69 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43705457/article/details/103979660