【问题标题】:Python Multithreading basics confusionPython多线程基础混淆
【发布时间】:2016-08-26 04:24:58
【问题描述】:

我有以下代码:

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 的理解是正确的,总时间(开始 - 结束)应该是 20 秒(与以顺序方式而不是线程方式运行一样好)......但它有点接近 5 秒。 ...为什么?归根结底,线程正在按顺序(尽管不是全部)一个接一个地执行 请外行解释一下,我的理解哪里不对?

Que3:如果我使用多处理做同样的事情会怎样?执行会有什么不同?

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 multithreading multiprocessing python-2.x gil


    【解决方案1】:

    Python 中的阻塞调用(sleep,等待 I/O 或锁)释放 GIL,允许其他线程在被阻塞时运行,因此所有四个线程都可以并行 sleep,这就是为什么你要看到五秒钟的延迟。如果您想查看 GIL 争用的影响,请让线程函数执行 CPU 绑定的操作,例如

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

    multiprocessing 不会改变 sleep 的情况,因为您不受 GIL 约束,但如果您有多个内核可以运行,它会改善 CPU 绑定情况的挂钟时间.

    【讨论】:

      【解决方案2】:

      Q1:是的

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

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

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多