python中的多线程是一个神话吗?

时间:2017-06-28 03:53:15

标签: python multithreading multiprocessing

据我所知,可以在系统内同时生成多个线程,但是2个不同的线程不能同时访问或修改同一个资源。我甚至尝试过很多东西,例如创建许多线程并将它们放入队列等等。但是我总是听到人们说多线程在Python中不可用,而是你可以使用多处理来利用多核CPU。

我是真的吗? Python线程只是绿色线程,而不是真正的多线程吗?我对Python的资源锁定是对的吗?

2 个答案:

答案 0 :(得分:7)

不,Python确实有多线程。实际上,它使用系统线程。问题只是它不能使用多个可用内核。这是因为GIL(Global Interpreter Lock). Python线程仍然适用于I / O绑定任务,而CPU绑定任务可能会导致死锁和竞争条件。许多Python库通过使用C扩展来绕过GIL来解决这个问题。当然,这就是CPython的情况。

Python的一位核心开发人员对此进行了非常有趣的讨论。

Thinking about concurrency, Raymond Hettinger

现在你是对的,使用多处理来获得所有核心的好处要好得多。但是核心比线程少得多。核心是宝贵的资源,占用大量内存。如果您不介意处理IPC(Interprocess Communication),那么这是一个很好的解决方案。

答案 1 :(得分:5)

Python中的多线程是一种神话。

技术上没有什么可以禁止多个线程同时尝试访问同一个资源。结果通常是不可取的,因此开发了诸如锁,互斥体和资源管理器之类的东西。它们是确保一次只有一个线程可以访问给定资源的不同方法。实质上,它们使线程一起发挥得很好。但是,如果花费很多线程的时间等待资源,那么你就不会从多线程中获得任何好处,而你最好还是编写一个单线程程序(或者重构你的程序以避免等待)

话虽如此,在CPython(最流行的Python实现 - 你点击https://python.org上的下载按钮或通过包管理器获得的实现)中,有这种邪恶的必然性称为Global Interpreter Lock( GIL)。为了使CPython中的动态内存管理正常工作,GIL可以防止多个线程同时运行Python代码。这是因为CPython的动态内存管理不是线程安全的 - 它可能同时存在多个线程访问(或更糟,处置)相同资源的相同问题。 GIL是在不允许多线程代码的两个极端之间的折衷,并且动态内存管理非常庞大和缓慢。

其他实现(如JythonIronPython,但不是PyPy)没有GIL,因为它们构建的平台(Java for Jython,.NET for IronPython) )处理动态内存管理的方式不同,因此可以安全地在多个线程中同时运行Python代码。

如果您使用的是CPython,强烈建议您使用multiprocessing模块。它不是运行多个线程,而是运行多个进程(每个进程都有自己的GIL,因此它们可以同时运行)。它比多线程更有效。另一种方法是将您的多线程代码用C / C ++编写为扩展,因为本机代码不受GIL的约束。然而,这通常需要做更多工作,而且回报通常不值得付出努力。

关于绿色线程:它们不会像通常意义上那样实现多线程。 Green threads更接近coroutines,因为它们(通常)无法利用多个处理器内核以真正的并行方式运行。相反,它们通常实现cooperative multitasking,其中每个绿色线程将手动将控制权传递给另一个绿色线程。 Stackless Python内置了对绿色线程的支持,greenlet扩展将它们带到了CPython。可能还有其他库/模块可以实现绿色线程,但我不熟悉其他任何库。