Python的GIL问题

python GIL问题的解释(global interpreter lock)
早期cpython(python最主要的解释器)为了实现多线程的功能,提高CPU利用率,暴力无脑使用了GIL机制(全局锁)来解决线程之间数据同步问题。
也就是因为历史问题埋了大坑。

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

在GIL的机制下,正常的cpu切换步骤中,在线程获得cpu时间片后,还需要获得GIL才能够执行。
在单核时代,这种机制是ok的,因为只有在GIL释放之后才会触发OS的线程调度,那么这时候其它线程势必能够获取GIL,实现线程的切换执行。
如果是多核心,那么就有问题了,因为只有一把大锁GIL,那么势必在任何时候,只能有一个线程在执行,也就是说只有一个cpu核心真正执行代码。
在多核架构下的线程调度,就会出现:虽然线程获得了cpu时间片,然而确没有得到GIL只好白白浪费CPU时间片,然后等待切换进入等待,等待下一次被唤醒,如此恶性循环。

现象:多线程的执行可能还不如单线程执行的时间开销

import threading
import time


def hehe(repeat):
    a=0
    for _ in xrange(repeat):
        a += 1
    print a

t1=threading.Thread(target=hehe,args=(100000000,))
t2=threading.Thread(target=hehe,args=(100000000,))
start=time.time()
print start
t1.start()
t1.join()

t2.start()
t2.join()

end=time.time()
print end
print end-start


# t1=threading.Thread(target=hehe,args=(100000000,))
# t2=threading.Thread(target=hehe,args=(100000000,))
# start=time.time()
# print start
#
# t1.start()
# t2.start()
# t1.join()
# t2.join()
#
#
# end=time.time()
# print end
# print end-start

总结:
假如在多核计算机上进行IO密集型的计算,python的多线程确实可以提高效率;
如果线程中只要有一个是CPU密集型的线程,那么多线程效率可能会因为GIL反而下降

http://dabeaz.blogspot.com/2010/02/revisiting-thread-priorities-and-new.html

http://cenalulu.github.io/python/gil-in-python/

原文地址:https://www.cnblogs.com/dijkstra-c/p/10371709.html