提问人:frankfalse 提问时间:10/5/2023 最后编辑:frankfalse 更新时间:10/6/2023 访问量:62
为什么子进程继承的线程处于停止状态,而父进程处于已启动状态?
Why the thread inherited by the child process is in the stopped status while in parent process is in the status started?
问:
安全地分叉多线程进程是有问题的
我正在学习使用该模块。现在我专注于以下句子: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
p1
- 另请参阅该方法返回的不同值(在 Main 中为 true,在
is_alive()
p1
) - 前面的考虑因素得到了以下事实的证实:在进程中,变量的值始终是 而在主进程中,线程增加了 。
p1
a
1
t1
问题
为什么子进程继承的线程处于停止状态,而父进程处于已启动状态?
此行为与句子“请注意,安全地分叉多线程进程是有问题的”有关。
答:
1赞
David Schwartz
10/5/2023
#1
为什么子进程继承的线程处于停止状态,而父进程处于已启动状态?
我想最好有一些状态来表明该线程从未真正存在过。但是线程在子进程中停止,因为该线程从未存在于子进程的上下文中。
如果你问为什么线程没有在子线程中运行,那是因为这会导致绝对的混乱。假设线程位于与某些服务交互的库函数中。复制线程可能会导致该服务上的操作序列无效。
此行为与句子“请注意,安全地分叉多线程进程是有问题的”有关。
我想是的。例如,假设在调用 时,其他线程之一保持锁定。该锁永远不会在子进程中释放,因为解锁它的线程不存在。fork
评论
0赞
frankfalse
10/5/2023
谢谢大卫。你的句子“假设线程位于与某些服务交互的库函数中。复制线程可能会导致该服务上的操作序列无效“,这正是我对使用该模块的疑虑之一。multiprocessing
评论