全局静态初始化线程

2023-12-01

我有一个用互斥体保护的集合。初始化后,它只能被读取,所以我在那里不需要互斥体。

该集合在全局静态初始值设定项中进行初始化和填充。我知道全局静态初始化是在单个翻译单元内保证的。是否可以保证全局静态初始化是单线程的?


我有一个受 Schwarz 计数器保护的静态集合,并由其他静态对象的构造函数填充。该容器与互斥锁相关联。鉴于该集合在之后是只读的main开始,如果我可以保证在单个线程中调用静态构造函数,我想摆脱互斥体。

我的理解是,静态初始化顺序通常在单个翻译单元内明确定义,但在翻译单元之间未指定。标准是否允许静态对象由不同的运行时提供的线程初始化/构造?


施瓦茨计数器:

头文件:

struct Init
{
   Init();
   ~Init();
};
namespace
{
   Init _init;
}
extern std::map<int, std::unique_ptr<...>> &protected;

源文件:

namespace
{
   int init_count;
   std::aligned_storage<sizeof(std::map<int, std::unique_ptr<...>>), alignof(std::map<int, std::unique_ptr<...>>>)> protected_storage;
}
std::map<int, std::uniqe_ptr<...>> &protected = *reinterpret_cast<std::map<int, std::unique_ptr<...>> *>(&protected_storage);
Init::Init()
{
   if (!init_counter++)
   {
      new(&protected_storage) std::map<int, std::unique_ptr<...>>();
   }
}
Init::~Init()
{
   if (!--init_counter)
   {
      protected.~std::map<int, std::unique_ptr<...>>();
   }
}

征集人群:

struct helper
{
   helper(...)
   {
      protected.insert(std::make_pair(...));
   }
};

扩展了一个宏,用于创建助手的静态实例。


是否可以保证全局静态初始化是单线程的?

你的意思是动态初始化。不,明确不保证单线程初始化。

从 3.6.2 开始:

如果一个程序启动了一个线程(30.3),则后续的初始化 变量的初始化相对于不同翻译中定义的变量是无序的 单元。否则,变量的初始化相对于初始化的顺序是不确定的 在不同翻译单元中定义的变量。如果程序启动一个线程,则后续的无序 变量的初始化相对于所有其他动态初始化是无序的。否则, 变量的无序初始化相对于所有其他动态是不确定地排序的 初始化

因此,如果您在程序中启动一个线程,那么理论上,来自两个不同 TU 的两个不同全局变量的构造函数可以同时从两个不同线程运行。

处理这些问题的最佳方法是将静态存储持续时间变量包装为以下“单例模式”中的局部静态变量:

const T& f()
{
    static T t(a,b,c);
    return t;
}

最新标准保证了建设t是线程安全的,因此您根本不需要互斥体(至少不需要明确指定,编译器将为您生成防护)。

作为一个额外的好处,该对象是在第一次调用时“惰性”构造的f,因此您无需担心初始化顺序。如果多个这样的单例在其构造函数中相互调用(当然,前提是依赖关系是非循环的),它们将以工作顺序进行初始化。非局部变量的情况并非如此。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

全局静态初始化线程 的相关文章

随机推荐

  • 如何让 perf stat 支持 KVM 中的“分支”、“分支未命中”等硬件事件

    我想通过 分支未命中 硬件事件来评估一个进程的性能 但是当我使用 perf stat 获取 分支未命中 数据时 它总是返回 0 因为我的操作系统位于 KVM 中 因为我拿一台真机来做测试比较麻烦 所以我想知道当我在 KVM 中时 有什么方法
  • 具有多个模板的 ASP Repeater 控件

    如何拥有具有多个模板的转发器控件 其中选择的模板基于项目的类型 这就是我目前所拥有的 我的复读班 ToolboxData lt 0 LifestreamRepeater runat server gt public class Lifest
  • 变异观察者产生无限循环

    我正在使用 jQuery 的突变观察器编写一个函数来注册对 DOM 的更改 特别是在添加新节点时 以便我可以更改其内容 SELeCTOR GOOD click function var targetNode this find conten
  • 表达 sendfile 和重定向 url

    我有一堆中间件 一开始app use我测试该过程是否受到胁迫 如果是 我希望它只发送静态 index html文件并将用户的浏览器重定向到 req url 例如 app set port PORT etc app use function
  • 设置 R_LIBS 并避免“您想使用个人库吗?”

    我的个人库在 Renviron中设置为R LIBS R lib 当我从 rstudio 安装软件包时 这非常有效 当我尝试从普通 R 控制台会话安装新软件包时 它总是询问我 Would you like to use a personal
  • 可以使用缓冲读取来计算 MD5(或其他)哈希值吗?

    我需要计算相当大的文件 千兆字节 的校验和 这可以使用以下方法来完成 private byte calcHash string file System Security Cryptography HashAlgorithm ha Syste
  • 向非引用类型添加生命周期约束

    我试图弄清楚如何应用 Rust 生命周期来向 Erlang NIF 模块添加一些编译时强制 NIF 模块是通常用 C 编写的提供扩展的共享库 用 C 语言编写的回调的简化原型如下所示 Handle my nif function Heap
  • 如何在 Zend Framework 2 中获取控制器名称、操作名称

    我在 Zend Framework 2 中有一个默认模块 namespace Application Controller use Zend Mvc Controller AbstractActionController use Zend
  • 任一类型包含不同类型

    原始帖子已编辑为简化示例 我想创建一个组件 该组件将采用一对值 这两个值都基于相同类型 gt value setValue 并且基于它 将运行取决于这些类型的函数 为了充分说明情况 AnimalAndCatTypes ts export i
  • 如何使用 C 从用户空间获取 Linux 中的驱动器标签

    我需要在 Linux 中使用 c c 并且没有 d bus 获取特定设备的标签 问题是我不能只打开设备并读取它的信息 对于 extN 来说 很容易从设备获取标签 因为从 dev xxx 读取需要 root 权限 我认为现在在大多数发行版中都
  • 从 FullCalendar (jQuery) 中删除事件源时出现问题

    就在那时 我正在使用全日历显示来自多个源的事件 一些是本地 JSON feed 另一些来自 Google Calendar 我实现了一项功能 当复选框分别为 true 或 false 时 可以显示 隐藏单个日历 我正在使用这段代码来实现它
  • 如何从Delphi运行命令行?

    如何从我的 Delphi 应用程序运行此命令 C myapppath appfolder gt appname exe stext save txt 我尝试了以下代码 ShellExecute 0 nil cmd exe cd C myap
  • 在 SetWindowPos() 中获取跨线程操作无效

    我试图从与创建表单的线程不同的线程访问表单 最后出现错误 跨线程操作无效 Code public static void MakeTopMost Form form SetWindowPos form Handle HWND TOPMOST
  • 如何使用许多 OR 替代方案来缩短长 XPath 表达式?

    我正在努力让 Selenium 遍历大量替代条件 XPath 寻找满足以下条件的元素 可能匹配 并将其传递给对象elmnt 目前 使用OR操作员 代码很快就会变得非常重复和详尽 尤其是当存在很多可能的变化时 在下面的示例中 唯一的变化是我开
  • WKWebView确实从本地文档文件夹加载资源

    在我的 Swift iOS 应用程序中 我想从远程服务器下载一些动态 HTML 页面 将它们保存在文档目录中 并从文档目录中显示这些页面 我用它来加载页面 var appWebView WKWebView appWebView loadRe
  • Azure 服务主体可以更新自己的密码吗?

    我需要以编程方式使用 Azure 服务主体 1 添加 删除其他服务主体的密码 以及2 为自身添加 删除密码 1很容易做到 但由于以下错误 我似乎无法执行 2 2可能吗 如何 graphrbac PasswordCredentialsUpda
  • po [NSThread 当前线程]

    当我执行 po NSThread currentThread 时 我得到了 名称 空 数字 4 When I look to the left I see 看起来线程号是 6 而不是 4 另外 我们需要调用哪些属性来获取线程号 NSThre
  • 当方向改变时如何管理应用程序?

    我有一个正在更改屏幕方向的应用程序 但是 当我更改第一个屏幕的方向并转到下一个屏幕时 更改不会持续 附上图片以便更清楚地理解 主要问题是 当设备旋转时 第一个屏幕会旋转 但第二个屏幕不会以新方向启动 仅当我们在屏幕启动后改变方向时它才会旋转
  • 如何在 Python 类中创建增量 ID

    我想为我创建的每个对象创建一个唯一的 ID 这是该类 class resource cl def init self Name Position Type Active self Name Name self Position Positi
  • 全局静态初始化线程

    我有一个用互斥体保护的集合 初始化后 它只能被读取 所以我在那里不需要互斥体 该集合在全局静态初始值设定项中进行初始化和填充 我知道全局静态初始化是在单个翻译单元内保证的 是否可以保证全局静态初始化是单线程的 我有一个受 Schwarz 计