Python多线程基础知识混乱

时间:2016-08-26 04:24:58

标签: python multithreading multiprocessing python-2.x gil

我有以下代码:

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分钟。为什么?我无法理解。

3 个答案:

答案 0 :(得分:3)

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

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

multiprocessing不会改变sleep的情况,因为你不是GIL绑定的,但是如果你有多个,它会改善CPU绑定情况的挂钟时间运行的核心。

答案 1 :(得分:2)

Q1:是的

Q2:如果每个线程都做了5秒的处理时间,那么你可以期望总时间为20秒。但每个线程只是休眠5秒钟,因此每个线程释放GIL,从而允许其他线程并行运行" (仅在概念上),因为它等待睡眠超时。

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

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

答案 2 :(得分:1)

用于python中的多线程环境。我们有两种非常不同的类型:

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