Python是运行在解释器中的语言,查找资料知道,python中有一个全局锁(GIL),在使用多线程(Thread)的情况下,不能发挥多核的优势。而使用多进程(Multiprocess),则可以发挥多核的优势真正地提高效率。
单线程、多线程和多进程的效率对比测试: github地址
资料显示,如果多线程的进程是CPU密集型的,那多线程并不能有多少效率上的提升,相反还可能会因为线程的频繁切换,导致效率下降,推荐使用多进程;如果是IO密集型,多线程进程可以利用IO阻塞等待时的空闲时间执行其他线程,提升效率。所以我们根据实验对比不同场景的效率
| CPU密集型操作| IO密集型操作| 网络请求密集型操作
-- | -- | --| --
线性操作| 69.73533328374 |17.76633326213 | 6.78833333651
多线程操作| 75.40299995740 |145.68366670609 | 1.93999997775
多进程操作| 13.97433336576 | 4.67833328247| 2.38333328565
仅个人观点,,欢迎留言~~~
因为Python是单线程,所以并行动作是不可能的,以下代码供参考。from threading import Thread, active_count
from queue import Queue
from turtle import Screen, Turtle
screen = Screen()
a = Turtle('square', visible=False)
a.speed('slow')
a.color('red')
a.penup()
a.setx(-300)
a.setheading(0)
a.pendown()
a.showturtle()
b = Turtle('circle', visible=False)
b.speed('slow')
b.color('green')
b.penup()
b.setx(300)
b.setheading(180)
b.pendown()
b.showturtle()
a.forward(300)
b.forward(300)
screen.mainloop()
def move(turtle):
turtle.forward(1)
if turtle.distance(0, 0) >1:
screen.ontimer(lambda t=turtle: move(t), 50)
move(a)
move(b)
QUEUE_SIZE = 1
def process_queue():
while not actions.empty():
action, *arguments = actions.get()
action(*arguments)
if active_count() >1:
screen.ontimer(process_queue, 100)
actions = Queue(QUEUE_SIZE)
def move(turtle):
while turtle.distance(0, 0) >1:
actions.put((turtle.forward, 1))
Thread(target=move, args=[a], daemon=True).start()
Thread(target=move, args=[b], daemon=True).start()
process_queue()
有必要,至少能解决很多IO阻塞问题。能产生IO阻塞的情况很多,比如网络、磁盘,等等。当发生阻塞时,Python是不耗CPU的,此时如果就一个线程就没法处理其他事情了。所以对于含有IO阻塞的环境。多线程至少有机会让你把一个CPU核心跑到100%。
另一个用处来自于Python的C扩展模块。在扩展模块里是可以释放GIL的。但释放GIL期间不应该调用任何Python API。所以,对于一些非常繁重的计算,可以写成C模块,计算前释放GIL,计算后重新申请GIL,并将结果返回给Python。这样就可以让Python这个进程利用更多的CPU资源。每个Python的线程都是OS级别pthread的线程。利用Python来管理这些线程比在C层级操作pthread更方便。