2013-12-21 45 views
1
from concurrent.futures import ThreadPoolExecutor, as_completed 

def main(): 
    with ThreadPoolExecutor(max_workers=16) as producersPool: 
     for i in [1,2,3,4,5,6,7,8,9,0]: 
      producersPool.submit((lambda i : print(i))(i)) 


if __name__ == "__main__": 
    main() 

與python3運行:爲什麼Python的GIL強制執行嚴格的處理順序?

1 
2 
3 
4 
5 
6 
7 
8 
9 
0 

總是相同的。

現在我想讓你知道我的意思 - 我不一定希望這些任務重新排序,但我只是想知道爲什麼訂購發生在?我的意思是,人們可以期望在一個線程內以確定性的方式完成事情,但嚴格排隊的線程對我來說似乎有點奇怪。

無論如何,我如何在Python 3中獲得真正的併發性? (就我所知,Jython和IronPython僅支持2.x)。

+1

您的示例包含一個重要錯誤:您實際上是_calling_ lambda,並且只會將_result_(通常爲None)傳遞給'submit'。觀察到的行爲與ThreadPool無關。你可能想寫'(lambda i:(lambda:print(i)))(i)'。 – l4mpi

+0

@ l4mpi,是的,我已經注意到它,並已經擊中了自己的臉。我將代碼編輯爲'producersPool.submit(sleepy,i)',它按預期運行,即是一種相當不可預測的時尚。謝謝。 – tkroman

回答

5

所有作業都在之前執行它們被提交,並且它們中的任何一個都不會寫入輸出流。您提交致電每個lambda結果

即使你使用:

producersPool.submit(lambda i: print(i), (i,)) 

沒有在每個線程足夠由另一個線程被搶佔,所以他們都完成任何其他線程之前,但在

+0

啊,我明白了。好吧,我加了'sleep(5)',它似乎現在以一種真正隨機的方式列出了這個列表。謝謝。 – tkroman

+0

這個例子中的實際問題是打印發生在主線程中,並且OP從不向線程池提交除None之外的任何東西... – l4mpi

+0

請參閱我對@ l4mpi的評論(lambdas在這裏看起來有點破舊IMO,所以我做了一個函數)。 – tkroman

2

回答你問題的第二部分:

"how do I get the real concurrency in Python 3?"

可以使用multiprocessing模塊:

"multiprocessing is a package that supports spawning processes using an API similar to the threading module. The multiprocessing package offers both local and remote concurrency, effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads."

由於您的示例中使用來自concurrent.futuresThreadPoolExecutor,都在同一個包一看ProcessPoolExecutor。它類似於ThreadPoolExecutor,但使用進程(而不是線程),所以它不受GIL的阻礙。

+0

是的,我看到了,但沒有想到可能性。這很好,我很抱歉我不能同時接受兩個答案(我不應該首先問兩個答案:)) – tkroman