【问题标题】:Is the initialisation of namespace-scope static storage duration variables thread safe?命名空间范围静态存储持续时间变量的初始化线程安全吗?
【发布时间】:2021-08-20 19:18:20
【问题描述】:

命名空间范围静态存储持续时间对象的初始化规则在here 中进行了描述。我选择了关于内联变量的段落作为例子,但问题对于非内联变量是相同的。它说:

"具有静态存储持续时间的非块内联变量的动态初始化是在main的第一条语句之前排序还是延迟,这是实现定义的。如果是延迟,它强烈发生在任何非-initialization odr-use of that variable. 它是实现定义的,在哪些线程和程序中的哪些点发生这种延迟的动态初始化。"

这似乎并不能保证初始化将由一个线程执行,如果不是这样,它就没有说明这些初始化是如何相互同步的。

我可以想象以下场景:线程 A 中的控件到达全局内联变量 x 的第一个 odr-use。此时,x 的初始化在线程 A 中开始。现在,在线程 A 中开始 x 的初始化之后,但在它完成之前,线程 B 达到了x 的第一个 odr-use。由于x仍在初始化过程中,它被认为是未初始化的,因此线程B也可能开始初始化它,导致数据竞争。

将上面的引用与here 描述的关于使用静态存储持续时间初始化块变量的引用进行比较。它说:

“具有静态存储持续时间或线程存储持续时间的块变量的动态初始化在控制第一次通过其声明时执行;这样的变量在其初始化完成时被认为已初始化。[...] 如果控制在变量初始化的同时进入声明,则并发执行等待初始化完成。"

为什么这个措辞如此不同?在并发上下文中初始化的安全性似乎更加明确。

也许我的问题的答案从上下文中是显而易见的 - 我不知道,这就是我问这个问题的原因。我真的很想知道标准提供了什么保证,不管我对编译器实现有什么期望。

【问题讨论】:

    标签: c++ multithreading language-lawyer undefined-behavior c++20


    【解决方案1】:

    这似乎并不能保证初始化将由一个线程执行

    “在该变量的任何非初始化 odr 使用之前发生”是所有标准需要说的。在 C++ 内存模型中。 “强烈发生在之前”意味着该事物的所有可见副作用都将被该事物的任何后续用户看到。

    您不能对“强烈发生在”您访问某事物之前的某事物进行数据竞赛。确实,“数据竞赛”的定义是explicitly predicated on not having a "happens before" relationship

    如果程序的执行包含两个潜在的并发冲突操作,则该程序的执行包含数据竞争, 至少其中一个不是原子的,也不会在另一个之前发生

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-17
      • 2010-12-30
      • 1970-01-01
      • 2012-05-22
      • 2018-06-11
      • 1970-01-01
      • 2010-10-27
      相关资源
      最近更新 更多