2012-11-30 16 views
5

La sequenza di disimballaggio è atomica? per esempio:La sequenza è decompressione atomica?

(a, b) = (c, d) 

Ho l'impressione che non lo sia.

Modifica: intendevo l'atomicità nel contesto del multithreading, ovvero se l'intera istruzione è indivisibile, come in passato erano gli atomi.

+1

Ho l'impressione che tu stia forse fraintendendo ciò che è * comunemente * inteso dall'atomicità nello sviluppo del software. Stai parlando di sicurezza dei thread qui, o ti stai chiedendo se 'a = c' sarà eseguito prima di' b = d'? –

+0

@MartijnPieters - Se OP si interrogasse su quest'ultimo, OP sarebbe molto confuso perché qualcosa come '(a, b) = (b, a)' potrebbe funzionare per scambiare valori. Deve essere una domanda sulla sicurezza del filo. –

+0

@TedHopp: La domanda è troppo vaga per chiamare questo, e nella mia esperienza tuple disfare provoca molta confusione in sé e per sé. –

risposta

6

È un'operazione; l'espressione di destra è valutata prima di applicare l'assegnazione di sinistra:

>>> 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) 

O, se si parla di ambienti multi-threaded, quindi la cessione è non atomica; l'interprete valuta un'assegnazione tupla con un singolo codice operativo, ma utilizza codici operativi separati per poi memorizzare i risultati in ciascuna variabile interessata:

>>> 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   

Tuttavia, normale assigment sta andando sempre essere almeno due codici operativi (uno per l'espressione di destra, una per memorizzare il risultato), quindi in python in generale l'assegnazione non è atomica. Sequenza di spacchettamento non è diverso.

+1

Penso che non sia un'espressione "atomica". anche 'j = i + 1' non è atomico nei linguaggi di alto livello. Ho 'Semaphore' in python .... Ho frainteso la domanda? –

+0

Questo non significa che sia atomico. La domanda è se 'a' e' b' siano assegnati ai loro valori atomicamente (cioè come operazione indivisibile) in un ambiente concorrente. Non credo che lo siano; cioè, se '(a, b)' dovessero finire con valori '(200, 2)' nell'ultimo passo, un altro thread potrebbe vedere '(200, 10)' o '(20, 2)'. –

+0

Ho frainteso la domanda (o meglio, ho scelto di interpretare la domanda molto scarna in termini di domande più frequenti sulle assunzioni di tuple). L'ho aggiornato per includere informazioni sulla sicurezza del thread. –

4

Sicuramente non atomico in un ambiente multi-thread, testato utilizzando il seguente script:

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 

testata usando CPython 2.6, 2.7 e 3.2. Su ogni versione questo script ha stampato "Not atomic" ed è uscito in meno di un secondo.

+1

Mi hai fatto ricontrollare gli opcode; lo spacchettamento è uno, ma poi ci sono due opcode STORE_FAST, uno per ogni variabile interessata. Un sacco di possibilità per un altro thread di assegnare qualcosa di diverso in mezzo. –