2009-11-08 66 views
11

我正在嘗試在我正在使用的Python項目中使用線程,但線程似乎沒有像我應該在代碼中那樣工作。看來所有線程都按順序運行(即線程2在線程1結束後開始,它們不會同時啓動)。我編寫了一個簡單的腳本來測試它,並且它也按順序運行線程。Python線程似乎按順序運行線程

import threading 

def something(): 
    for i in xrange(10): 
     print "Hello" 

def my_thing(): 
    for i in xrange(10): 
     print "world" 

threading.Thread(target=something).start() 
threading.Thread(target=my_thing).start() 

這裏的輸出我從運行它獲得:

Hello 
Hello 
Hello 
Hello 
Hello 
Hello 
Hello 
Hello 
Hello 
Hello 
world 
world 
world 
world 
world 
world 
world 
world 
world 
world 

同樣的行爲與更大的循環迭代次數觀察。

我試着搜索網頁和較老的答案,但我找不到任何有幫助的東西。 有人可以指出這段代碼有什麼問題嗎?

回答

13

目前在Python中,線程在執行了一些指定數量的字節碼指令後發生了變化。他們不同時運行。當它們中的一個調用一些I/O密集型或不能影響可釋放GIL(全局解釋器鎖)的影響Python的模塊時,您將只有並行執行線程。

我敢肯定你會得到輸出,如果你碰到的循環數爲類似10000記住,簡單地產卵的第二個線程還需要時間「很大的」混合起來。

+0

相同的行爲10000次迭代 – MAK 2009-11-09 05:26:44

+0

在我正在處理的實際項目中,其中一個線程是一個無限循環,用於偵聽消息並將回調函數稱爲他們到了。它只是阻止所有其他線程。不幸的是,實際的循環代碼不能被修改(我只是在線程中調用一個類的run()方法)。 – MAK 2009-11-09 05:31:00

+0

當我像這樣運行腳本時:'./pythr.py | uniq -c'我得到:8969你好| 1你好world | 6626世界| 1 | 3373世界| 1030你好。所以它確實改變了控制權 - 只是沒有那麼經常...... – viraptor 2009-11-09 09:33:43

10

第二個線程開始第一個線程循環打印的時間已經耗盡。

在這裏看起來像這樣,你可以看到第二個線程在第一個發出幾個hellos後開始。

Hello 
Hello 
Hello 
Hello 
Hello 
Helloworld 

Helloworld 

Helloworld 

Helloworld 

Helloworld 

world 
world 
world 
world 
world 

順便說一句:你的例子根本沒有意義。線程唯一的原因是IO,IO很慢。當你添加一些睡眠模擬IO,應該按預期工作:出現

import threading 
from time import sleep 

def something(): 
    for i in xrange(10): 
     sleep(0.01) 
     print "Hello" 

def my_thing(): 
    for i in xrange(10): 
     sleep(0.01) 
     print "world" 

threading.Thread(target=something).start() 
threading.Thread(target=my_thing).start() 

野生搭配:

worldHello 

Helloworld 

Helloworld 

worldHello 

Helloworld 

Helloworld 

worldHello 

Helloworld 

worldHello 

Helloworld 
+2

即使for循環的迭代次數多得多/更少,我也不會得到這樣的輸出。在我的電腦上,它總是連續的。我認爲這是OS /處理器的依賴,就像abyx建議的那樣。 – MAK 2009-11-08 20:16:17

+0

正如我在我的問題中所說的,這僅僅是我的問題的一個例子,而不是我正在使用的代碼(這是更大的代碼)。在我的實際代碼中,其中一個線程運行一個監聽dbus信號的循環。 – MAK 2009-11-09 17:28:43

3

這真的取決於你的操作系統的程序,您的處理器。
除此之外,已知CPython的線程並不完美,因爲GIL(PDF),簡而言之,這意味着許多線程按順序運行,或者類似的東西。

+2

你可能是說CPython線程受GIL影響......比如說Jython沒有GIL。 – EOL 2009-11-09 13:29:33

+0

@EOL - 你是對的,我已經更新了答案 – abyx 2009-11-09 14:41:01

4

行爲也可能會改變,具體取決於系統使用的是單個處理器還是多個處理器,如David Beazley的this talk所解釋的。

由於viraptor說,第一個線程將執行sys.getcheckinterval()字節碼(默認爲100)後釋放GIL。爲了粗略地總結David Beazley所說的,在單個處理器系統上,第二個線程將有機會接管。但是,在多核系統上,第二個線程可能運行在不同的內核上,第一個線程將嘗試重新獲取該鎖並且可能成功,因爲操作系統沒有時間切換處理器。這意味着在具有CPU綁定線程的多核系統上,其他線程可能永遠無法查看。

這樣做的方法是向兩個循環添加睡眠語句,以便它們不再CPU綁定。