Python 线程和 GIL

标签 python multithreading gil

假设我有一个线程和程序的主要部分。由于 GIL,一个线程应该一次工作(而不是同时工作)吗?但是,如果其中一个线程是一个无限循环(或两者都是无限循环)怎么办?

这两个进程会并行运行吗?

def test():
    while True:
       print "hello"

def test2():
    while True:
       print "hi"

def start_thread():
    try: 
        thread.start_new_thread( test2,() )
    except:
        print "Error: Unable to start thread"
start_thread()
test()

最佳答案

它们会同时运行,但实际上不是并行。操作系统会频繁地在两个线程之间来回切换,以便它们都能完成各自的工作。这就是“并发”的意思;一个线程不需要等待另一个线程完成就可以开始工作。但是由于 GIL,它们实际上永远不会同时运行,每个都在不同的内核上并行运行。每个线程都会运行一段时间,在另一个线程运行时暂停,然后再次开始运行,然后暂停,等等。

如果您只是运行您的示例代码,这很容易查看。这是我机器上的输出:

hello
hi
hello
hi
hello
hi
hello
hi
hello
hi
hello
hi
hello
hi
hello
hi
hello
hi

很明显,两个线程都在运行。每个线程的运行速度都比程序中只有一个线程运行时慢。

考虑这个例子,其中每个线程计算斐波那契数列:

import thread
import time


def fib(n):
    if n <= 1:
        return n

    return fib(n-1) + fib(n-2)

def test():
    while True:
       start = time.time()
       out = fib(32)
       print "hello %s: %s" % (out, str(time.time() - start))

def test2():
    while True:
       out = fib(20)

def start_thread():
    try: 
        thread.start_new_thread( test2,() )
    except:
        print "Error: Unable to start thread"
#start_thread()
test()

只有 test 运行(所以没有第二个线程),我得到这个输出:

hello 2178309: 0.953778982162
hello 2178309: 0.954975128174
hello 2178309: 0.95578789711
hello 2178309: 0.949182033539

如果我也在后台启动 test2,我会得到这个:

hello 2178309: 4.07990288734
hello 2178309: 4.08523893356
hello 2178309: 2.51651597023
hello 2178309: 2.13291287422
hello 2178309: 2.19885015488

如您所见,性能会受到巨大影响。

请注意,如果其中一个线程正在做一些释放 GIL 的事情——比如阻塞 I/O,或者调用释放 GIL 的 C 库——你不会看到这种性能下降,因为在那种情况下这两个线程实际上可以并行运行。这不适用于上面的示例,因为两个线程都没有执行释放 GIL 的工作。

关于Python 线程和 GIL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29704445/

相关文章:

python - 使用python扩展字符串中的环境变量

c# - 多个实时图形在自己的线程中,全局 60fps 限制?

python - spacy-io 如何在没有 GIL 的情况下使用多线程?

python - 是否有通用的方法来测试 GIL 的存在?

python - 获取第一个数组的行与第二个数组的行相匹配

python - 自定义 python 回溯或调试输出

python - python 'module' object has no attribute 'write_dataframe' 错误的 Feather 数据存储库

swift - 如何在 Swift 中使用多线程

multithreading - "How many links do I have?",询问 Erlang 进程

java - 为什么Java虚拟机中没有GIL?为什么 Python 这么需要一个?