多线程似乎是顺序执行的
我在做一个Python项目,想用线程来提高效率,但我发现我的代码里的线程好像没有按预期工作。看起来所有的线程都是一个接一个地运行,也就是说,线程2要等线程1结束后才能开始,它们并没有同时启动。我写了一个简单的脚本来测试这个情况,结果也是线程一个接一个地运行。
import threading
def something():
for i in xrange(10):
print "Hello"
def my_thing():
for i in xrange(10):
print "world"
threading.Thread(target=something).start()
threading.Thread(target=my_thing).start()
这是我运行这个脚本时得到的输出:
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
world
world
world
world
world
world
world
world
world
world
即使是循环的迭代次数增加,情况也是一样。
我尝试在网上搜索相关信息和以前的回答,但没有找到任何有用的内容。有没有人能告诉我这段代码哪里出问题了?
5 个回答
这个行为可能会因为系统是单个处理器还是多个处理器而有所不同,正如David Beazley在这场演讲中所解释的。
正如viraptor所说,第一个线程在执行sys.getcheckinterval()的字节码后会释放全局解释器锁(GIL),默认情况下是100个字节码。简单来说,在单处理器系统上,第二个线程就有机会接管。但是在多核系统上,第二个线程可能会在不同的核心上运行,而第一个线程会尝试重新获取这个锁,通常会成功,因为操作系统还没有时间切换处理器。这意味着在多核系统中,如果有一个线程占用了CPU,其他线程可能就没机会运行了。
解决这个问题的方法是在两个循环中添加一个睡眠语句,这样它们就不再占用CPU了。
在第二个线程启动的时间里,第一个线程已经循环并打印出内容了。
这里的情况是这样的,你可以看到第二个线程在第一个线程已经输出了几次“你好”之后才开始运行。
Hello
Hello
Hello
Hello
Hello
Helloworld
Helloworld
Helloworld
Helloworld
Helloworld
world
world
world
world
world
顺便说一下:你的例子其实没有什么意义。线程的主要用途是处理输入输出,而输入输出的速度比较慢。当你加入一些“睡眠”来模拟输入输出时,它应该就能按预期工作了:
import threading
from time import sleep
def something():
for i in xrange(10):
sleep(0.01)
print "Hello"
def my_thing():
for i in xrange(10):
sleep(0.01)
print "world"
threading.Thread(target=something).start()
threading.Thread(target=my_thing).start()
出现了一种奇妙的混合:
worldHello
Helloworld
Helloworld
worldHello
Helloworld
Helloworld
worldHello
Helloworld
worldHello
Helloworld
现在在Python中,线程在执行一定数量的字节码指令后会切换。也就是说,它们并不是同时运行的。只有当其中一个线程调用一些需要大量输入输出操作的模块,或者是那些不影响Python的模块时,才能实现线程的并行执行,这样可以释放全局解释器锁(GIL)。
如果你把循环的次数增加到像10000这样的数字,我敢肯定你会发现输出会混在一起。记住,单单启动第二个线程也需要“很多”时间。