为了底层管理方便,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非常值得一看。
今天看完后非常震惊,跟大家分享一下 :)
1
Septembers 2015-05-10 00:12:15 +08:00
from threading import Thread
换成 from multiprocessing import Process as Thread 其他原封不动 |
2
MonkLuf OP @Septembers 你想表达的意思是?
|
4
secondwtq 2015-05-10 10:35:51 +08:00
Python, Ruby, Lua, JavaScript 等脚本语言貌似没有一个有多线程并行的支持的(在 JVM,.Net 上面实现的另说)... 感觉在脚本语言的基础上面这个确实不太好搞
|