Python 多线程基础混乱

Python Multithreading basics confusion

我有以下代码:

import time
from threading import Thread

def fun1():
 time.sleep(5)

def fun2():
 time.sleep(5)

def fun3():
 time.sleep(5)

def fun4():
 time.sleep(5)

if __name__ == '__main__':
  t1 = Thread(target=fun1, args=())
  t2 = Thread(target=fun2, args=())
  t3 = Thread(target=fun3, args=())
  t4 = Thread(target=fun4, args=())
  t1.start()
  t2.start() 
  t3.start() 
  t4.start()
  start = time.clock()
  t1.join()
  t2.join()
  t3.join()
  t4.join()
  end = time.clock()
  print("Time Taken = ",end-start)

Que1: 一次只有一个线程被服务,意思是如果控制是线程t1,其余线程将等待。一旦线程 t2 发生上下文切换,其余所有线程(t1、t3 和 t4)将等待。 这样理解对吗?

Que2:如果我对 Que1 的理解是正确的,总时间(开始 - 结束)应该是二十秒(与 运行 顺序方式而不是线程方式一样好)......但它是有点接近 5 秒....为什么?在一天结束时,线程正在按顺序(尽管不是全部)一个接一个地执行 请外行解释一下terms.Where我的理解有误吗?

问题 3:如果我使用多处理做同样的事情怎么办?执行会有何不同?

Que4:假设(假设)fun1() 的代码对路由器 1 执行 1000 次重复计数 ping,耗时 1 分钟。 类似地,fun2() 对路由器 2 执行 1000 次重复计数 ping,耗时 1 分钟。 类似地,fun3() 对路由器 3 执行 1000 次重复计数 ping,耗时 1 分钟。

如果我按顺序执行此操作,总预期时间为 3 分钟(ping 到 R1,然后 ping 到 R2,然后 ping 到 R3) 但是当我使用线程执行此操作时,总执行时间几乎接近 1 分钟。为什么 ?看不懂。

在 Python 中阻塞调用(sleep,等待 I/O 或锁定)释放 GIL,允许其他线程在被阻塞时 运行,所以所有四个线程可以 sleep 并行,这就是您看到五秒延迟的原因。如果你想看到 GIL 竞争的影响,让线程函数做一些 CPU 绑定,例如

def fun():
    for _ in xrange(1000000000):
        pass

multiprocessing 不会改变 sleep 情况,因为您不受 GIL 限制,但它会改善 CPU 情况下的挂钟时间如果你有多个核心 运行 on.

Q1:是

Q2:如果每个线程执行某项操作需要 5 秒的处理时间,那么您预计总时间为 20 秒。但是每个线程只休眠 5 秒,因此每个线程释放 GIL,从而允许其他线程 运行 "in parallel"(仅在概念上),因为它等待休眠超时。

Q3:与 threads 不同,多处理创建的子进程每个 运行 可以在不同的处理器上并发(实际上是并行的)。但即使这些 sleeps 每个 运行 在不同的处理器上,它们仍然会在大约 5 秒内共同完成。如果它们 运行 在同一个处理器上,OS 的分时机制将以类似于 Python 的线程机制的方式确保它们在大约 5 分钟内完成。

Q4:和sleep是同一个概念。每个 ping 都不是 CPU 密集型的,因此它的线程很少拥有 GIL。这允许所有三个 ping 线程在概念上并行 运行。

对于 python 中的多线程环境。我们有两种截然不同的任务:

  • CPU 绑定:比如加数字,运行ning for 循环......任何消耗 CPU 的活动。这种任务占用 GIL,因此它阻止了其他线程 运行ning.
  • 未CPU绑定(可能正在等待来自网络等外部资源的IO活动......):睡眠系统调用不使用CPU所以它是这种类型。这种在等待 IO、睡眠超时时释放 GIL .. 所以其他线程可以锁定和 运行ning。 这就是为什么您的程序需要大约 5 秒的原因,因为您的所有线程都可以 运行 并行。