Python线程和GIL

Lui*_*ruz 5 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()
Run Code Online (Sandbox Code Playgroud)

dan*_*ano 6

它们会同时运行,但实际上并不是并行运行.操作系统会频繁地在两个线程之间来回切换,这样他们就能完成工作.这就是"并发"的含义; 一个线程在开始工作之前不需要等待另一个线程完成.但是由于GIL,它们实际上永远都不会在同一时间运行,每个都在并行运行在不同的核心上.每个线程将运行一段时间,在另一个线程运行时暂停,然后再次开始运行,然后暂停,等等.

这很容易看到你是否只运行你的示例代码.这是我机器上的输出:

hello
hi
hello
hi
hello
hi
hello
hi
hello
hi
hello
hi
hello
hi
hello
hi
hello
hi
Run Code Online (Sandbox Code Playgroud)

显然,两个线程都在运行.如果程序中只运行一个线程,则每个线程的运行速度都比较慢.

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

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()
Run Code Online (Sandbox Code Playgroud)

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

hello 2178309: 0.953778982162
hello 2178309: 0.954975128174
hello 2178309: 0.95578789711
hello 2178309: 0.949182033539
Run Code Online (Sandbox Code Playgroud)

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

hello 2178309: 4.07990288734
hello 2178309: 4.08523893356
hello 2178309: 2.51651597023
hello 2178309: 2.13291287422
hello 2178309: 2.19885015488
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,性能受到了巨大冲击.

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