2016-08-26 60 views
1

我有下面的代碼:Python的多線程基礎知識混亂

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秒....爲什麼?在一天結束時,線程逐個按順序執行(儘管並非全部) 請用外行的詞彙解釋。我的理解在哪裏不正確?如果我使用多重處理做同樣的事情會怎樣?執行有何不同? (假設)fun1()的代碼對路由器1進行1000次重複次數ping,並花費1分鐘的時間。 同樣,fun2()對路由器2執行1000次重複計數ping,並花費1分鐘的時間。 Similary,fun3()對路由器3進行1000次重複計數ping,並花費1分鐘的時間。

如果我這樣做順序,總預計時間爲3分鐘(ping到R1,然後ping到R2,然後ping到R3) 但是當我使用線程做到這一點時,總執行時間幾乎接近1分鐘。爲什麼?我無法理解。

回答

2

Q1:是

Q2:如果每個線程做了一些花了5秒的處理時間,那麼你所期望的總時間爲20秒。但是每個線程只會休眠5秒,因此每個線程都會釋放GIL,從而允許其他線程「並行」(僅在概念上)運行,因爲它會等待睡眠超時。

Q3:與threads不同,多處理創建了可以同時在不同處理器上運行(實際上是並行)的子進程。但即使這些sleeps每個在不同的處理器上運行,它們仍將在大約5秒內共同完成。如果他們運行在相同的處理器上,OS的分時機制將以類似於Python的線程機制的方式,也確保它們在大約5分鐘內完成。

Q4:與sleep的概念相同。每個ping不是CPU密集型的,因此它的線程很少擁有GIL。這允許所有三個ping線程在概念上並行運行。

3

阻止Python中的調用(sleep,等待I/O或鎖)釋放GIL,允許其他線程在阻塞時運行,因此所有四個線程可以並行地sleep,這就是爲什麼你看到一個五第二次延遲。如果你想看到GIL爭用的影響,讓線程函數做一些CPU綁定的事情,例如

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

multiprocessing不會改變任何事情的sleep情況下,因爲你沒有GIL的約束,但它會提高CPU的約束情況下的掛鐘時間,如果你有一個以上的核心上運行。

1

用於python中的多線程環境。我們有兩種截然不同的類型:

  • CPU綁定:像添加數字,運行循環...任何消耗CPU的活動。這種任務保存GIL,以防止其他線程運行。
  • 沒有CPU綁定(可能正在等待來自外部資源的IO活動,如網絡...):睡眠系統調用不使用CPU,因此它是這種類型。這種類型在釋放GIL的同時等待IO,睡眠超時......所以其他線程可以鎖定並運行。 這就是爲什麼你的程序需要5秒左右的時間,因爲你的所有線程都可以並行運行。