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

问题描述 投票:0回答:1

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

我正在学习使用

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

输出显示进程

p1
具有对全局变量
t1
的引用,该变量指向类
Thread
的实例。但是在主进程中,线程处于状态
started
,当在进程中时
p1
处于状态
stopped
。另请参阅方法
is_alive()
返回的不同值(Main 中的 truep1 中的
false
)。
这一切似乎都得到了证实,即在进程中,变量
p1
的值始终为
a
,而在主进程中,变量
1
的值由线程增加
t1

问题

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

python linux multithreading multiprocessing fork
1个回答
1
投票

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

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

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

此行为与“请注意,安全分叉多线程进程是有问题的。”这句话相关联?

我想是这样。例如,假设当您调用

fork
时,其他线程之一持有锁。该锁永远不会在子进程中释放,因为解锁它的线程不存在。

© www.soinside.com 2019 - 2024. All rights reserved.