【问题标题】:Synchronisation in fork()ed multithreaded processfork()ed 多线程进程中的同步
【发布时间】:2013-09-06 21:30:41
【问题描述】:

如果我有一个创建 N 个线程的进程;即 T1 .... Tn。假设 N 个线程正在使用锁 L 在它们之间进行同步。如果这个进程调用fork()

  1. 新创建的子进程有 N 个线程还是只有 1 个线程?来自this question,看起来只有 1 个线程
  2. 锁 L 被复制到具有相同值的新 内存(物理)位置,对吧?
  3. 如果对问题 (1) 的回答是只有 1 个线程被复制,如果 T1 已锁定 L 并且从另一个线程 T2 调用 fork(),那么在新进程中会发生什么。 L 会一直被锁定吗?

【问题讨论】:

    标签: multithreading synchronization thread-safety fork


    【解决方案1】:

    新进程最初只有一个正在运行的线程。该进程的互斥锁副本将永远锁定,除非明确重新初始化或互斥锁已跨进程共享(属性 PTHREAD_PROCESS_SHARED,并非所有地方都支持)。

    以下是规范在讨论pthread_atfork() 时对这种情况的说明,该功能的引入部分是为了解决这种不愉快:

    考虑一个线程有一个互斥锁并且状态 当另一个线程调用时,该互斥体覆盖的不一致 叉()。在子进程中,互斥体处于锁定状态(由 不存在的线程,因此永远无法解锁)。让孩子简单地重新初始化互斥锁是不能令人满意的,因为这种方法不能解决如何纠正或以其他方式处理孩子的不一致状态的问题。

    【讨论】:

      【解决方案2】:
      1. 除非在生成线程之前调用 fork(),否则它只会独立运行。分叉不会复制子线程/进程。
      2. 进程堆中的数据在分叉时被复制到新进程(很可能使用写时复制)如果锁存储在堆中,它将获得自己的副本,因为进程有自己的堆。
      3. 使用常规锁(而不是信号量),任何线程都可以锁定/解锁它。

      【讨论】:

      • "如果锁存储在堆中,它会得到自己的副本。如果你为它分配内存,它不会被复制"分配内存是从堆中完成的,对吧?
      • 我明白了。因此,如果锁来自堆,则只会复制“指针值”,即“虚拟地址空间”中的锁地址。但是对于孩子和父母来说,都会有“单独的物理副本”。我说对了吗?
      • 好吧,我混淆了我的术语,我已经起床太晚了。在这种情况下,malloc 分配了堆数据,所以是的,您将获得一个全新的锁副本。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-17
      • 1970-01-01
      • 2019-05-05
      • 2021-06-12
      相关资源
      最近更新 更多