为了底层管理方便,Python多线程执行时,同一时刻只能有一个线程真正在执行,这样非常影响Python多线程的并发能力。
举个例子,计算从1到1亿的所有自然数之和,用一个线程算和用两个线程算的结果:
单线程:
def xsum(a, b):
s = 0
while a < b:
s += a
a += 1
print s
N = 100000001
xsum(1, N)
多线程:
from threading import Thread
def xsum(a, b):
s = 0
while a < b:
s += a
a += 1
print s
N = 100000001
p1 = Thread(target=xsum, args=(1, N/2))
p2 = Thread(target=xsum, args=(N/2, N))
p1.start(); p2.start()
p1.join(); p2.join()
这两个在我的机器上的计算结果是:
$ time python single.py
5000000050000000
real 0m5.910s
user 0m5.899s
sys 0m0.009s
$ time python par.py
3750000075000000
1249999975000000
real 0m8.661s
user 0m7.638s
sys 0m5.761s
我的机器,Core i7, 4核。多线程并发比单线程慢了46%!
这是因为GIL(Global Interpreter Lock)的存在。Python的程序在线程在执行时需要获取GIL锁才能继续,所以在同一时刻只能有一个线程在真正执行。一方面线程不能利用多核,另一方面线程竞争锁带来的抖动给实际的执行带来了很大的负载。这直接导致线程的性能非常差。
David Beazley,在PyCON'2010上做了一个精彩的演讲,深入浅出的讲解了Python GIL的机制。
网址: http://www.dabeaz.com/GIL/ ,其中那个PDF非常值得一看。
今天看完后非常震惊,跟大家分享一下 :)
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.