2016-08-29 64 views
2

據我所知,全局解釋器鎖只允許一個線程訪問解釋器並執行字節碼。如果是這樣的話,那麼在任何時候,只有一個線程會使用解釋器和它的內存。爲什麼我必須擔心CPython中的線程安全性?

因此,我認爲排除出現種族情況的可能性是公平的,因爲沒有兩個線程可以同時訪問解釋器的內存,但我仍然看到有關確保數據結構「線程安全」的警告, 。有可能它會覆蓋python解釋器的所有實現(比如cython),它可以關閉GIL並允許真正的多線程。

我明白在沒有啓用GIL的解釋器環境中線程安全的重要性。但是,對於CPython,爲什麼在編寫多線程Python代碼時鼓勵線程安全?在CPython環境中會發生什麼更糟?

回答

6

當然,競爭條件仍然可以發生,因爲訪問數據結構是而不是原子

說你測試的關鍵存在於詞典,然後做什麼要補充的關鍵:

if key not in dictionary: 
    # calculate new value 
    value = elaborate_calculation() 
    dictionary[key] = value 

線程可以在任何時候進行切換not in測試返回真後,和另一線程也會得出結論,關鍵不在那裏。現在有兩個線程正在進行計算,而你不知道哪一個會贏。

GIL所做的就是保護Python的內部解釋器狀態。這並不意味着Python代碼本身使用的數據結構現在被鎖定和保護。

0

一個重要的注意事項:即使GIL,Python中的多處理模塊在一定程度上是同步的,因爲對同一變量的訪問可以同時發生在不同的進程中。

這有可能破壞您的數據,或者至少干擾您的控制流,這就是爲什麼要建議線程安全的原因。

至於爲什麼發生這種情況,儘管只有一個interpriter,但是沒有任何事情停止(至少據我所知),兩個預先插入代碼的代碼片段可以同時訪問共享內存的相同部分。這樣做的時候說:

import multiprocessing 
def my_func(): 
    print("hello world") 
my_process=multiprocessing.Process (target=my_func, args=(,)) 
my_process.start() 
my_process.join() 

我的理解是,它需要interprit(在這種情況下)my_func,並將時間被埋葬在它需要產生新的進程的開銷。

在這種情況下,術語「進程」在這裏更合適,因爲有工作線程臨時產生只是爲了複製數據,所以有一些數據握手進行,所以它實際上是相當不同的一個過程(雙關語)比傳統線程的產卵。

我希望這會有所幫助。

相關問題