提问人:MAK 提问时间:11/9/2009 最后编辑:martineauMAK 更新时间:8/25/2022 访问量:14831
线程似乎按顺序运行线程
threading appears to run threads sequentially
问:
我正在尝试在我正在处理的 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
在循环的迭代次数要多得多的情况下,也会观察到相同的行为。
我尝试在网上搜索较旧的 SO 答案,但我找不到任何有帮助的东西。 有人可以指出这段代码有什么问题吗?
答:
在第二个线程启动第一个线程所需的时间内,已经循环和打印。
这里看起来像这样,你可以看到第二个线程在第一个线程发出几个问候后开始。
Hello
Hello
Hello
Hello
Hello
Helloworld
Helloworld
Helloworld
Helloworld
Helloworld
world
world
world
world
world
顺便说一句:你的例子根本没有意义。线程的唯一原因是 IO,而 IO 很慢。当您添加一些睡眠来模拟 IO 时,它应该按预期工作:
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
评论
这实际上取决于您的操作系统的调度程序,即您的处理器。
除此之外,众所周知,由于 GIL(PDF),CPython 的线程并不完美,简而言之,这意味着很多时候线程确实是按顺序运行的,或者类似的东西。
评论
目前在 python 中,线程在执行一定数量的字节码指令后会发生变化。它们不会同时运行。只有当其中一个线程调用一些 I/O 密集型或不影响 python 的模块时,您才会有线程并行执行,这些模块可以释放 GIL(全局解释器锁)。
我很确定,如果你将循环数提高到 10000 左右,你会把输出弄混。请记住,简单地生成第二个线程也需要“很多”时间。
评论
./pythr.py | uniq -c
multiprocessing
threading
行为也可能根据系统使用的是单个处理器还是多个处理器而改变,正如 David Beazley 的演讲所解释的那样。
正如 viraptor 所说,第一个线程将在执行 sys.getcheckinterval() 字节码(默认为 100)后释放 GIL。粗略地总结一下 David Beazley 所说的话,在单个处理器系统上,第二个线程将有机会接管。但是,在多核系统上,第二个线程可能在不同的内核上运行,第一个线程将尝试重新获取锁,并且可能会成功,因为操作系统没有时间切换处理器。这意味着,在具有 CPU 密集线程的多核系统上,其他线程可能永远无法查看。
解决此问题的方法是向两个循环添加一个 sleep 语句,以便它们不再受 CPU 限制。
通常,秘诀是始终确保在启动线程时使用以下语法。
Note threading.Thread(target=threadSet1).start() the function threadSet1 has not brackets at the end.
import threading
from time import sleep
def spawn(num, typex):
import time
start = time.time()
print(num, typex)
def threadSet1():
for i in range(1000):
sleep(0.01)
t = threading.Thread(target=spawn(i, "world"))
t.daemon = True
t.start()
def threadSet2():
for i in range(1000):
sleep(0.01)
t = threading.Thread(target=spawn(i, "hello"))
t.daemon = True
t.start()
if __name__ == '__main__':
threading.Thread(target=threadSet1).start()
threading.Thread(target=threadSet2).start()
不要陷入使用以下语法的陷阱,因为它会串行线程地执行它们。线程(target=threadSet1()).start()
线程。线程(target=threadSet2()).start()Note the functions have brackets at the end.
评论