为什么子进程继承的线程处于停止状态,而父进程处于已启动状态?

Why the thread inherited by the child process is in the stopped status while in parent process is in the status started?

提问人:frankfalse 提问时间:10/5/2023 最后编辑:frankfalse 更新时间:10/6/2023 访问量:62

问:

安全地分叉多线程进程是有问题的

我正在学习使用该模块。现在我专注于以下句子:multiprocessing

请注意,安全地分叉多线程进程是有问题的。

出现在官方文档中专门介绍上下文和启动方法的部分。

关于这个话题,我已经阅读了这个答案,其中包含以下声明:

“请注意,安全地分叉多线程进程是有问题的”:这里的 Problematic 是“不可能”的委婉说法。

测试代码

我已经编写了这个测试代码(用于 Linux 平台):

import multiprocessing
import threading
import time

a = 1
t1 = None

def thread_function_1():
    global a
    while True:
        time.sleep(2)
        a += 1

def p1():
    global a
    global t1
    while True:
        time.sleep(1)
        print(f"Process p1 ---> a = {a}, t1 = {t1}, t1 is_alive = {t1.is_alive()}")

if __name__ == "__main__":
    multiprocessing.set_start_method('fork')
    t1 = threading.Thread(target = thread_function_1)
    t1.start()
    p = multiprocessing.Process(target=p1)
    p.start()
    while True:
        a += 1
        time.sleep(1)
        print(f"Thread Main ---> a = {a}, t1 = {t1}, t1 is_alive = {t1.is_alive()}")

我在 Linux 上运行代码,所以指令:

multiprocessing.set_start_method('fork')

选择一个启动方法,该方法已经是 Linux 上的默认启动方法。这是因为对于测试,我使用的是 Python 3.6(来自文档:默认启动方法将更改为 Python 3.14 中的 fork。

其执行的输出为:

Thread Main ---> a = 2, t1 = <Thread(Thread-1, started 140618847368960)>, t1 is_alive = True
Process p1 ---> a = 1, t1 = <Thread(Thread-1, stopped 140618847368960)>, t1 is_alive = False
Thread Main ---> a = 4, t1 = <Thread(Thread-1, started 140618847368960)>, t1 is_alive = True
Process p1 ---> a = 1, t1 = <Thread(Thread-1, stopped 140618847368960)>, t1 is_alive = False
Thread Main ---> a = 5, t1 = <Thread(Thread-1, started 140618847368960)>, t1 is_alive = True
Process p1 ---> a = 1, t1 = <Thread(Thread-1, stopped 140618847368960)>, t1 is_alive = False
Thread Main ---> a = 7, t1 = <Thread(Thread-1, started 140618847368960)>, t1 is_alive = True
Process p1 ---> a = 1, t1 = <Thread(Thread-1, stopped 140618847368960)>, t1 is_alive = False

输出显示:

  • 该进程具有对全局变量的引用,该变量指向类的实例;但在主进程中,线程处于已启动状态,而在进程中处于已停止状态p1t1Threadp1
  • 另请参阅该方法返回的不同值(在 Main 中为 trueis_alive()p1)
  • 前面的考虑因素得到了以下事实的证实:在进程中,变量的值始终是 而在主进程中,线程增加了 。p1a1t1

问题

为什么子进程继承的线程处于停止状态,而父进程处于已启动状态?
此行为与句子“请注意,安全地分叉多线程进程是有问题的”有关。

python linux 线程 多处理 分支

评论


答:

1赞 David Schwartz 10/5/2023 #1

为什么子进程继承的线程处于停止状态,而父进程处于已启动状态?

我想最好有一些状态来表明该线程从未真正存在过。但是线程在子进程中停止,因为该线程从未存在于子进程的上下文中。

如果你问为什么线程没有在子线程中运行,那是因为这会导致绝对的混乱。假设线程位于与某些服务交互的库函数中。复制线程可能会导致该服务上的操作序列无效。

此行为与句子“请注意,安全地分叉多线程进程是有问题的”有关。

我想是的。例如,假设在调用 时,其他线程之一保持锁定。该锁永远不会在子进程中释放,因为解锁它的线程不存在。fork

评论

0赞 frankfalse 10/5/2023
谢谢大卫。你的句子“假设线程位于与某些服务交互的库函数中。复制线程可能会导致该服务上的操作序列无效“,这正是我对使用该模块的疑虑之一。multiprocessing