2010-07-29 216 views

回答

28

這兩個概念是完全不同的。 Thread safety意味着兩個線程不能同時修改同一個對象,從而使系統處於不一致的狀態。

也就是說,您不能在迭代它時修改字典。請參閱documentation.

詞典p在迭代期間不應該發生變異。在遍歷字典時,修改密鑰值是安全的(從Python 2.1開始),但只有在 密鑰集沒有更改時纔會修改。

+3

我認爲他們是相關的。如果一個線程迭代而另一個線程修改字典呢? – 2013-05-30 08:15:40

13

不。最近版本的python會引發異常,如果您嘗試遍歷迭代之間已更改大小的字典。

>>> d={'one':1, 'two':2} 
>>> for x in d: 
... d['three']=3 
... print x 
... 
two 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
RuntimeError: dictionary changed size during iteration 

請注意,您不需要使用線程來看看這個

58

其他的答案已經正確地解決什麼是顯然您的實際問題:

這是否意味着我可以或不可以修改 字典中的項目,而 迭代它?

解釋說,線程安全無關,與在任何情況下的問題,,不,你不能在遍歷它修改的字典。

然而,你的問題的標題爲約線程安全的,你開始:

有的說,蟒蛇詞典 線程安全

我不知道是誰「一些」是,但是,如果他們確實聲明(而不是你誤解他們所做的狀態;-)沒有重資質,他們是錯誤的。

一些操作,那些不改變鍵組在快譯通,恰好是線程安全的在當前的CPython實現 - 但你應該數量上,除非你嚴格控制您的代碼將在其下運行的Python版本,因爲Python的語言規範不保證此類線程的安全性,因此其他實現(包括未來版本的CPython)可能不會提供它。如果每個線程只是「讀取」字典(對它進行索引,對其進行循環等),並且沒有線程執行任何賦值或刪除操作,那麼在當前的CPython實現中這種情況是安全的;實際上,如果某個線程爲已存在的鍵分配了一個新值,那也是線程安全的(其他線程可能會看到該鍵或之後的值,這取決於線程是如何定時的,但在當前的CPython實現中,不會出現崩潰,沒有死鎖,並且不會出現任何瘋狂的值。

但是,操作如d[k] += 1(假設K是先前存在,其價值數)嚴格地說線程安全的(任何超過其他情況+=!),因爲它可以被看作是d[k] = d[k] + 1 - - 它可能可能發生競爭條件中的兩個線程都讀取舊值d[k],然後增加一個,並在槽中存儲相同的新值...所以總體效果是增加它只有一個,而不是通常會發生的兩次。

回到你的另一個問題......「只讀」的字典,賦予字典中已經存在的鍵的新值,也是你可以在迭代的循環體中做的事情字典 - 您無法更改字典中的一組密鑰(您不能添加任何密鑰,也不能移除任何密鑰),但允許爲現有密鑰設置新值的具體操作。在這種情況下允許的操作包括+=,這在線程情況下會有問題。例如:

>>> d = dict.fromkeys(range(5), 0) 
>>> for k in d: d[k] += 1 
... 
>>> d 
{0: 1, 1: 1, 2: 1, 3: 1, 4: 1} 

行爲由Python的標準化語義保證,所以語言的不同實現都應該保護它。

+0

你首先說:「如果每個線程只是」讀「字典(索引它,循環等),並且**沒有線程執行任何賦值或刪除操作,那麼在當前的CPython實現中這種情況是安全的** 「,最後你說:」允許爲現有的鍵設置一個新的值的具體操作... ...這種行爲由Python的標準化語義**保證,所以不同的語言實現應該保留它」。我很難區分這兩種情況。你能詳細說一點嗎?提前致謝! – RayLuo 2016-09-14 06:30:17