【问题标题】:std::atomic for built-in types - non-lock-free vs. trivial destructor?内置类型的 std::atomic - 非无锁与微不足道的析构函数?
【发布时间】:2017-05-09 13:38:25
【问题描述】:

查看std::atomic,这是我阅读的默认专业:

这些特化具有标准布局、普通默认构造函数普通析构函数

我也为is_lock_free阅读:

除了std::atomic_flag之外的所有原子类型都可以使用 互斥体 或其他锁定操作,而不是使用无锁 原子 CPU 指令。有时也允许原子类型 无锁,例如如果只有对齐的内存访问是自然原子的 在给定的架构上,相同类型的未对齐对象必须 使用锁。

现在这是我没有得到的问题:

标准规定琐碎的ctor/dtor的任何atomic类型怎么可能使用任何类型的互斥锁——我遇到的所有互斥锁都需要-简单的初始化。

这会导致以下问题:

  • 主要平台是否提供每个对象“无需初始化”的任何锁定操作(如互斥锁)。 (那将是“其他锁定操作”。)
  • 目前是否有任何已知的默认std::atomic 特化实现不是无锁的(并且仍然满足琐碎的ctor/dtor要求)?
  • 我只是在这里混淆了什么吗? :-)

在我看来,即使是最简单的自旋锁(参见atomic_flag)也需要不平凡的初始化,所以我看不出如何实现。

免责声明:纯粹出于学术兴趣,因为我在阅读这些文档时有点跳出来。

【问题讨论】:

    标签: c++ multithreading mutex atomic lock-free


    【解决方案1】:

    这里有一个可能的解决方案:如果一个原子操作使用了一个锁,但有一个普通的构造函数和析构函数,那么互斥锁可能是一个在多个原子值之间共享的全局互斥锁。

    我相信这是标准作者允许的情况。在某些常见平台(例如 POSIX)上,可以对具有静态持续时间的互斥锁使用普通的构造函数和析构函数。

    // This is copied plain C here, not C++
    // So nothing fancy
    #include <pthread.h>
    pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
    

    如果允许std::atomic 默认构造函数不平凡,那么在初始化期间将很难使用它们。

    std::atomic<int> my_flag;
    

    因为my_flag有一个普通构造函数,所以它是静态初始化的。静态初始化发生在动态初始化之前。因此,您可以确定所有全局 std::atomic 变量在您的构造函数运行之前都已初始化。

    【讨论】:

    • 哈!是的,这似乎可以满足标准要求。不过,对于大多数现实世界的用例来说,这似乎有点疯狂!
    • 是的,这看起来很疯狂。但人们想编写在疯狂架构上运行的 C++ 代码,标准作者有义务。
    • 写。您的编辑:代码不是 trivial 初始化,因为它将(静态)对象设置为一个值。 (?) 当然,任何使用 this 的对象都不需要做任何事情,因此可以有一个微不足道的 ctor。
    • 我觉得很奇怪的是允许锁定实现(好吧,那又怎样)但 需要 微不足道的构造/破坏。对于我需要一个互斥体来实现std::atomic_int 的架构,让这种类型进行非平凡的初始化(因为它必须携带一个互斥体)来拥有 all i> atomic_int 对象共享同一个互斥体。我想这是一个设计问题,所以无论如何。
    • @MartinBa:使用非平凡的构造函数意味着任何顶级静态原子变量的初始化都将是“不确定顺序的”,这对于在初始化期间需要原子同步的代码尤其成问题。这是一种相当普遍的情况,因此标准委员会需要一个普通的构造函数/析构函数是有道理的,特别是因为普通平台无论如何都会有一个普通的构造函数/析构函数。
    猜你喜欢
    • 2013-09-11
    • 1970-01-01
    • 2020-07-18
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 2017-05-17
    相关资源
    最近更新 更多