基本python多线程问题

用户

不熟悉python并尝试理解多线程。下面是关于Queue的python文档中的一个示例

在我的生活中,我不明白这个例子是如何工作的。在worker()函数中,有一个无限循环。工人们怎么知道什么时候该离开这个圈子?似乎没有破坏条件。在

最后的连接到底在做什么?我不是应该加入线程吗?在

def worker():
    while True:
        item = q.get()
        do_work(item)
        q.task_done()

q = Queue()
for i in range(num_worker_threads):
    t = Thread(target=worker)
    t.daemon = True
    t.start()

for item in source():
    q.put(item)

q.join()       # block until all tasks are done

还有一个问题,什么时候应该使用多线程,什么时候应该使用多处理?在


已被浏览了2869次
更新日期: 2020-09-28 06:11:13
3 个回答
fefe Tyson

是的。你说得对。worker将永远运行。但是,由于队列只有有限数量的项,最终worker将在q.get()处永久阻塞(因为队列中不再有项目)。在这一点上,worker仍在运行是无关紧要的。q.join()阻塞,直到队列计数下降到0(每当工作线程调用q.task_done,计数就会下降1)。节目结束后。无限阻塞的线程和它的创造者一起死去。在

评论 - 2020年8月7日 16:59
fefe Tyson

同意joel cornett,大多数情况下。我尝试在python2.7中运行以下代码片段:

^{1}$

输出为:

^{pr2}$

我认为最可能的解释是:

当队列在任务耗尽后变为空时,父线程在从q.join()返回后退出并销毁队列。子线程在接收到“item=q.get()”中产生的第一个TypeError异常时终止,因为队列不再存在。在

评论 - 2020年8月7日 16:59
fefe Tyson

关于您的第二个问题,Python中线程和进程之间的最大区别是主流实现使用全局解释器锁(globalinterpretor lock,GIL),以确保多个线程不会扰乱Python的内部数据结构。这意味着,对于那些大部分时间都用纯Python进行计算的程序来说,即使有多个cpu,也不会使程序的速度提高很多,因为一次只有一个线程可以保持GIL。另一方面,在Python程序中,多个线程可以简单地共享数据,在某些情况下(但并非全部),您不必太担心线程安全性。在

多线程可以加速Python程序的地方是程序将大部分时间花在等待I/O磁盘访问,或者特别是现在的网络操作上。GIL不是在执行I/O时保持的,因此许多Python线程可以在I/O绑定的应用程序中并发运行。在

另一方面,对于多处理,每个进程都有自己的GIL,因此您的性能可以根据可用的CPU核数量进行调整。缺点是进程之间的所有通信都必须通过多处理队列(在表面上的作用很像排队。排队,但有着非常不同的底层机制,因为它必须跨进程边界进行通信)。在

由于处理线程安全或进程间队列可以避免许多潜在的线程问题,而且由于Python使其非常简单,multiprocessing模块非常有吸引力。在

评论 - 2020年8月7日 16:59

最新Python问答

推荐Python问答