理解python线程错误

时间:2012-11-02 10:17:24

标签: python python-multithreading

阅读http://bugs.python.org/msg160297,我可以看到一个由Stephen White编写的简单脚本,它演示了python线程如何在此异常中出错

Exception AttributeError: AttributeError("'_DummyThread' object has no attribute '_Thread__block'",) in <module 'threading' 

鉴于Stephen White的源代码(http://bugs.python.org/file25511/bad-thread.py),

import os
import thread
import threading
import time

def t():
    threading.currentThread() # Populate threading._active with a DummyThread
    time.sleep(3)

thread.start_new_thread(t, ())

time.sleep(1)

pid = os.fork()
if pid == 0:
    os._exit(0)

os.waitpid(pid, 0)

我们如何重新编写它以便解决此错误?

1 个答案:

答案 0 :(得分:34)

发生

The bug是因为在外部线程上调用threading时由threading.currentThread() API创建的虚拟线程对象与调用的threading._after_fork函数之间的交互不良在致电os.fork()后清理资源。

要在不修改Python源代码的情况下解决错误,使用threading._DummyThread的无操作实现来修补__stop

import threading
threading._DummyThread._Thread__stop = lambda x: 42

Richard Oudkerkcooyeah在评论中最好缩小错误原因。会发生以下情况:

  1. threading模块允许从非threading.currentThread() API调用创建的线程调用threading。然后它返回一个“虚拟线程”实例,该实例支持Thread API的非常有限的子集,但仍然可用于识别当前线程。

  2. threading._DummyThread是作为Thread的子类实现的。 Thread个实例通常包含一个内部可调用(self.__block),它可以引用为该实例分配的操作系统级锁。由于可能最终使用Thread的公开self.__block方法被_DummyThread覆盖,_DummyThread的构造函数通过删除self.__block来故意释放操作系统级锁定

  3. threading._after_fork打破了封装,并在所有已注册的线程上调用私有Thread.__stop方法,包括虚拟的线程,其中__stop从未打算调用。 (它们不是由Python启动的,所以它们的停止也不是由Python管理的。)由于虚拟线程不知道__stop,它们从Thread继承它,并且该实现很愉快地访问__block个实例中不存在的私有_DummyThread属性。此访问最终会导致错误。

  4. 当删除__block时,错误在modifying Thread.__stop not to break的{2.7}分支中得到修复。 3.x分支,__stop拼写为_stop并因此受到保护,将其修复为overriding _DummyThread's _stop to do nothing