2012-11-30 29 views
5

序列解包原子?例如:序列拆包原子?

(a, b) = (c, d) 

我感覺不到它。

編輯:我在多線程,即整個語句是否是不可分割的,因爲原子曾經是的上下文中的意思原子性。

+1

我的印象是,你也許什麼是*一般*通過原子在軟件開發中理解誤區下。你在說這裏的線程安全嗎,還是你想知道'a = c'會在'b = d'之前執行? –

+0

@MartijnPieters - 如果OP想知道關於後者,OP會很困惑,爲什麼像'(A,B)=(B,A)'會工作交換價值。它必須是關於線程安全的問題。 –

+0

@TedHopp:這個問題太模糊了,不能稱之爲,根據我的經驗,tuple拆包會導致大量混淆。 –

回答

6

這是一個操作;應用了左手分配前右側表達式求值:

>>> a, b = 10, 20 
>>> a, b 
(10, 20) 
>>> b, a = a, b 
>>> a, b 
(20, 10) 
>>> a, b = a*b, a/b 
>>> a, b 
(200, 2) 

或者,如果你談論的多線程環境,然後分配是原子;解釋器的計算結果與單個操作碼的元組分配,但使用獨立的操作碼,以便然後存儲結果到每個受影響的變量:

>>> def t(self): a,b=20,20 
... 
>>> dis.dis(t) 
    1   0 LOAD_CONST    2 ((20, 20)) 
       3 UNPACK_SEQUENCE   2 
       6 STORE_FAST    1 (a) 
       9 STORE_FAST    2 (b) 
      12 LOAD_CONST    0 (None) 
      15 RETURN_VALUE   

然而,正常賦值是始終將是至少兩個操作碼(一個用於右手錶達,一個用於存儲結果),所以在一般分配新建分配FY蟒不是原子。序列拆包也不例外。

+1

我認爲這不是「原子」表達。即使'j = i + 1'在高級語言中也不是原子。我有Python中的信號量......我誤解了這個問題? –

+0

這並不能確定它是原子的。問題是'a'和'b'是否在併發環境中以原子方式分配它們的值(即,作爲不可分割的操作)。我不相信他們是;也就是說,如果'(A,B)'應該與值落得'(200,2)'中的最後一步,另一個線程可能會看到'(200,10)'或'(20,2)'。 –

+0

我誤解了這個問題(或者說,我選擇用關於元組分配的更常見的問題來解釋非常稀疏的問題)。我已經更新它以包含線程安全信息。 –

4

絕對不是在多線程環境中的原子,使用以下腳本進行了測試:

import threading 

a, b = 10, 10 
finished = False 
def thr(): 
    global finished 
    while True: 
     # if sequence unpacking and assignment is atomic then (a, b) will always 
     # be either (10, 10) or (20, 20). Could also just check for a != b 
     if (a, b) in [(10, 20), (20, 10)]: 
      print('Not atomic') 
      finished = True 
      break 

t = threading.Thread(target=thr) 
t.start() 

while True: 
    for i in range(1000000): 
     a, b = 20, 20 
     a, b = 10, 10 
    if finished: 
     t.join() 
     break 

使用CPython的2.6,2.7和3.2的測試。在每個版本上,這個腳本都打印出「不是原子的」,並在一秒鐘內退出。

+1

你讓我重新檢查操作碼;解包是一個,但是接下來有兩個STORE_FAST操作碼,每個操作碼對應一個受影響的變量。另一個線程有很多機會分配不同的東西。 –