试图理解python多线程 请考虑此代码: import threading def printer(): for i in range(2): with lock: print ['foo', 'bar', 'baz'] def main(): global lock lock = threading.Lock() threads = [threading.Thread(target=printer) for x in xrange(2)] for t in threads: t.start() t.join() main()
我可以理解这段代码,而且很清楚:我们创建两个线程,然后按顺序运行它们——我们只在第一个线程完成时运行第二个线程。好的,现在考虑另一个变型:试图理解python多线程 请考虑此代码: import threading def printer(): for i in range(2): with lock: print ['foo', 'bar', 'baz'] def main(): global lock lock = threading.Lock() threads = [threading.Thread(target=printer) for x in xrange(2)] for t in threads: t.start() t.join() main(),python,multithreading,Python,Multithreading,我可以理解这段代码,而且很清楚:我们创建两个线程,然后按顺序运行它们——我们只在第一个线程完成时运行第二个线程。好的,现在考虑另一个变型: import threading def printer(): for i in range(2): with lock: print ['foo', 'bar', 'baz'] def main(): global lock lock = threading.Lock() thre
import threading
def printer():
for i in range(2):
with lock:
print ['foo', 'bar', 'baz']
def main():
global lock
lock = threading.Lock()
threads = [threading.Thread(target=printer) for x in xrange(2)]
for t in threads:
t.start()
for t in threads:
t.join()
main()
这里发生了什么?好的,我们并行运行它们,但是在第二个变体中让主线程等待子线程的目的是什么?它如何影响输出?在第二个变体中,执行顺序的定义要少得多。 每次通过回路输入打印机时都会释放锁。在这两种变体中,一个线程中有两个线程和两个循环。 在第一个变体中,因为一次只运行一个线程,所以您知道总的顺序。 在第二种变体中,每次释放锁时,运行的线程可能会发生变化。 所以你可能会
- 线程1循环1
- 线程1循环2
- 线程2循环1
- 线程2循环2
在这种特殊情况下,我不确定第二个变量中对
t.join()
的调用是否有明显的效果。它保证主线程将是最后一个结束的线程,但我不确定在这段代码中您是否可以以任何方式观察到这一点。在更复杂的代码中,连接线程可能很重要,因此清理操作只能在所有线程终止后执行。如果您有守护进程线程,这一点也非常重要,因为当所有非守护进程线程终止时,整个程序将终止。要更好地理解python中的多线程,您需要首先了解主线程和子线程之间的关系
main
线程是程序的入口,它是在运行脚本时由系统创建的。例如,在脚本中,main
函数在main
线程中运行
而子线程
是在实例化线程
类时由主线程
创建的
最重要的是主线程如何控制子线程。基本上,Thread
的实例是main
线程知道并控制该子线程的所有内容。创建子线程时,该子线程不会立即运行,直到主线程在此线程实例上调用start
函数。在启动子线程之后,您可以假设main
线程和child
线程现在并行运行
但是更重要的一点是main
线程如何知道child
线程的任务已经完成。虽然main
线程不知道子线程如何完成任务,但它确实知道子线程的运行状态<代码>线程。是否处于活动状态
可以通过main
线程检查线程的状态。在实践中,Thread.join
函数总是用来告诉main
线程等待子线程完成。此函数将阻止main
线程
好的,让我们检查一下您混淆的两个脚本。对于第一个脚本:
for t in threads:
t.start()
t.join()
循环中的子线程是start
ed,然后是join
ed。请注意,start
不会阻止main
线程,而join
将阻止main
线程,直到该子线程完成。因此,它们是按顺序运行的
而对于第二个脚本:
for t in threads:
t.start()
for t in threads:
t.join()
所有子线程都在第一个循环中启动。由于Thread.start
函数不会阻止主线程
线程,因此所有子线程在第一个循环后并行运行。在第二个循环中,main
线程将逐个等待每个子线程的任务完成
现在我认为您应该注意到这两个脚本之间的区别:在第一个脚本中,子线程
线程逐个运行,而在第二个脚本中,它们同时运行
python线程还有其他有用的主题:
(1) 如何处理键盘中断异常,例如,当我想通过Ctrl-C
终止程序时?只有main
线程将接收异常,您必须处理子线程的终止
(2) 多线程与多处理。虽然我们说线程是并行的,但它并不是CPU级别的真正并行。因此,如果您的应用程序是CPU密集型的,请尝试多处理,如果您的应用程序是I/O密集型的,多线程可能就足够了
顺便说一下,请通读python线程部分的文档,并尝试一些代码,这可能有助于您理解它
希望这会有帮助。谢谢 它的目标是并行运行所有线程,以便同时完成多个作业。尽管Iirc,如果使用CPython实现运行,GIL将阻止它按预期运行。您可能需要澄清您的问题,因为这里不清楚您到底在问什么。调用thread.join
将等待线程完成执行。因此,第二种情况将启动两个线程运行,然后等待第一个线程完成,然后等待第二个线程完成。实际上,两个线程都将并行运行,哪一个先完成并不重要——主线程将有效地等待两个线程完成(先等待一个线程,然后等待另一个线程)