【问题标题】:Can I cause a Meyers singleton to reinitialize in forked child processes?我可以让 Meyers 单例在分叉的子进程中重新初始化吗?
【发布时间】:2021-07-04 18:23:01
【问题描述】:

假设我有一个迈耶斯单身

Data& get() {
  static Data data = initialization_work();
  return data;
}

已在父进程中使用和初始化。然后我 fork(2) 一个子进程,并且在子进程中 data 可能需要不同(即,我希望 initialization_work() 在子进程中第一次调用 get() 时重新运行)。

首先,data 会在分叉的孩子中自动重新初始化吗?我的怀疑是否定的,基于我对 linux 的平庸知识(分叉的子 VA 空间是映射到物理内存写入时复制的父级的副本,所以我假设子进程将看到 data 已经初始化并且不会重做initialization_work()) 和其他几个问题 (C static variables and linux fork, C++ static variable and multiple processes)。

其次,如果data不会默认在child中重新初始化,有没有办法在child第一次调用get()时强制重新初始化?如果没有,我可以尝试找出一些其他模式(我非常感谢任何关于哪种模式可能适合这个用例的建议)。

【问题讨论】:

  • @MartinYork: 1. 进程 ID 不同 :-P 2. 问题仍然存在,即使是关于原始进程...
  • 我在我应该之前回答了(所以我删除了它)。您是否想要它重新初始化,即使您得到@MartinYork 提到的(几乎)完全相同的副本?
  • 如果 pid 更改重置 data 的值,您可以将当前的 pid 保存在 get() 中?

标签: c++ linux c++11 fork


【解决方案1】:

首先,数据会在分叉的孩子中自动重新初始化吗?我的怀疑是没有

为什么只是怀疑?事实上,什么都不会被初始化。正如@MartinYork 所提到的——你会得到一份原始流程的副本。这就是分叉的魔力——无需初始化世界。父子进程都(几乎)仅根据 fork() 调用的返回值进行不同的操作。

第二,如果默认情况下不会在child中重新初始化数据,有没有办法在child第一次调用get()时强制重新初始化?

这与询问在原始进程中强制重新初始化单例的问题相同。现在,当然有办法……

【讨论】:

  • 使用std::optional 处理所有放置新的和显式的析构函数调用细节。
  • @BenVoigt:这也是个好主意。编辑它。
  • 在我看来,无论我是否使用 std::optional,孩子都需要知道是孩子来破坏和重建data,所以我需要检查 PID 什么的。这是你建议的隐含部分吗?
  • @MichaelCarilli:但是子进程确实知道它是子进程,基于fork() 的结果;这就是你检查的内容。
  • 对,我的意思是考虑到它的重要性,它应该在未来读者的答案中明确。我看到你添加了它,谢谢!
猜你喜欢
  • 2021-04-23
  • 1970-01-01
  • 2019-05-12
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
相关资源
最近更新 更多