回答

3

不,你的代碼不是線程安全的,因爲使用的字典值+=增量賦值需要3個操作碼來執行:

>>> dis.dis(compile("dic['key'] += 1", '', 'exec')) 
    1   0 LOAD_NAME    0 (dic) 
       3 LOAD_CONST    0 ('key') 
       6 DUP_TOPX     2 
       9 BINARY_SUBSCR 
      10 LOAD_CONST    1 (1) 
      13 INPLACE_ADD 
      14 ROT_THREE 
      15 STORE_SUBSCR 
      16 LOAD_CONST    2 (None) 
      19 RETURN_VALUE 

在9位的操作碼,BINARY_SUBSCR檢索從當前值詞典。操作碼9和15之間的任何位置(其中STORE_SUBSCR將數值放回),可能會發生線程切換,並且不同的線程可能已更新字典。

+0

謝謝!這就是我需要知道的,我知道dic是線程安全的,但我不確定+ @ – oshaiken

+0

@OlzhasShaikenov:字典不一定是線程安全的;如果要存儲的對象是定義了__hash__和/或__eq__的Python定義的類的實例,則在存儲對象和線程上下文切換時,解釋器將執行這些方法。 –

+0

這並不符合我對GIL及其目的所瞭解的一般閱讀理解。它的目的是讓單個操作碼線程安全嗎?在這方面有什麼具體的我可以搜索以瞭解GIL? – roganjosh

1

Python的內置結構對於單個操作是線程安全的。 GIL(全球解釋器鎖)負責照顧。但是很難看到一個聲明變成了更多的操作。

加把鎖會給你安心:

def somefunc(someparam): 
    if someparam: 
     with lock: 
      dic['key'] +=1 
+1

謝謝,我知道我可以使用鎖。問題是如果該特定操作是線程安全的,則http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm – oshaiken