use*_*956 7 python python-multiprocessing
根据 https://github.com/joblib/joblib/issues/180,有没有一种安全的方法从python中的线程创建子进程? Python多处理模块不允许在线程内使用.这是真的?
我的理解是,从线程中分叉是好的,只要你没有持有线程.当你这样做时(在当前线程中?在进程中的任何地方?).但是,Python的文档没有说明在fork之后是否安全地共享threading.Lock对象.
还有这个:从日志记录模块共享的锁导致fork问题.https://bugs.python.org/issue6721
我不确定这个问题是怎么产生的.听起来当进程中的任何锁的状态都被复制到当前线程分叉的子进程中(这看起来像设计错误并且肯定会死锁).如果是这样,那么使用多真正提供对这种任何保护(因为我可以自由地创建我multiprocessing.Pool被创建和被其它线程进入后threading.Lock,经过线程已经开始,使用不是叉安全日志模块) - 多处理模块docs也没有说明是否应该在Locks之前分配multiprocessing.Pools.
用多处理替换threading.Lock.Lock到处避免这个问题并允许我们安全地组合线程和分支?
听起来当进程中的任何锁的状态都被复制到当前线程分叉的子进程中(这看起来像设计错误并且肯定会死锁).
这不是设计错误,而是在fork()单进程多线程之前.所有锁的状态都被复制到子进程中,因为它们只是内存中的对象; 进程的整个地址空间被复制,就像在fork中一样.只有不好的选择:要么通过fork 复制所有线程,要么在多线程应用程序中拒绝分叉.
因此,fork()在多线程程序中从来不是安全的事情,除非在子程序之后execve()或之后exit().
用多处理替换threading.Lock.Lock到处避免这个问题并允许我们安全地组合线程和分支?
号没有使其能够安全线和叉结合,它无法做到的.
问题是,当一个进程中有多个线程时,fork()系统调用后无法继续在POSIX系统中安全地运行该程序.
例如,Linux手册fork(2):
也就是说,fork()在多线程程序中然后只调用异步信号安全的C函数(这是C函数的一个相当有限的子集),直到子进程被另一个可执行文件替换为止!
例如,子进程中的不安全C函数调用就是这样
malloc 用于动态内存分配<stdio.h>格式化输入的任何功能pthread_*线程状态处理所需的大多数功能,包括创建新线程......因此,儿童过程实际上可以安全地做的事情很少.不幸的是,CPython核心开发人员一直在淡化由此引起的问题.即使现在文档说:
请注意,安全分叉多线程进程存在 问题.
相当于"不可能"的委婉说法.
如果你没有使用start方法,那么从具有多个控制线程的Python进程使用多处理是安全的.在Python 3.4+中,现在可以更改start方法.在以前的Python版本中,包括所有Python 2,POSIX系统总是表现得好像被指定为start方法; 这会导致未定义的行为.forkfork
问题不仅限于threading.Lock对象,而是C标准库,C扩展等所持有的所有锁.更糟糕的是,大多数时候人们会说"它对我有用 "......直到它停止工作.
甚至有些情况下,看似单线程的Python程序实际上是在MacOS X中进行多线程处理,导致在使用多处理时出现故障和死锁.
另一个问题是所有打开的文件句柄,它们的使用,共享套接字在分叉的程序中可能表现得很奇怪,但即使在单线程程序中也是如此.
TL; DR:multiprocessing在多线程程序中使用,带有C扩展,带有打开的套接字等:
fork,| 归档时间: |
|
| 查看次数: |
1789 次 |
| 最近记录: |