2013-08-01 5 views
5

È un'operazione come a,b=1,2 atomica?Come verificare se un passaggio è un'operazione atomica in python o ora

Alcuni aspetti del mio problema: sto lavorando con il segnale. che vengono sollevati da qualche processo esterno. Qui voglio evitare i casi in cui il segnale viene catturato tra l'impostazione a=1 and b=2. C'è un modo per raggiungere questo obiettivo?

C'è un modo per controllare se il dato passo è atomico o no?

+0

Vedi anche: http://stackoverflow.com/questions/2623086/is-a-variable-swap-guaranteed-to-be-atomic-in-python – nemo

risposta

12

non è atomica, perché ci vuole più istruzioni bytecode da assegnare a più nomi e non ci vuole molto per confermare sperimentalmente:

import signal 

a = 1 
b = 2 

def handler(sig, trace): 
    print a, b 

def main(): 
    global a, b 
    signal.signal(signal.SIGINT, handler) 
    while True: 
     a, b = 3, 4 
     a, b = 1, 2 

if __name__ == '__main__': 
    main() 

$ python atom.py 
^C3 4 
^C3 4 
^C1 2 
^C1 2 
^C3 4 
^C1 2 
^C1 2 
^C1 2 
^C1 2 
^C1 4 <<<< inconsistent state 

In questo caso particolare, se si vuole due valori cambiare dal punto di vista atomico, è possibile cavarsela assegnando la tupla e accedendo ai suoi elementi nel gestore del segnale. Guardando lo smontaggio:

>>> a = 1 
>>> b = 2 
>>> c = (1, 2) 
>>> def foo(): 
...  global a, b 
...  a, b = 1, 2 
... 
>>> def bar(): 
...  global c 
...  c = (1, 2) 
... 
>>> dis.dis(foo) 
    3   0 LOAD_CONST    3 ((1, 2)) 
       3 UNPACK_SEQUENCE   2 
       6 STORE_GLOBAL    0 (a) 
       9 STORE_GLOBAL    1 (b) 
      12 LOAD_CONST    0 (None) 
      15 RETURN_VALUE   
>>> dis.dis(bar) 
    3   0 LOAD_CONST    3 ((1, 2)) 
       3 STORE_GLOBAL    0 (c) 
       6 LOAD_CONST    0 (None) 
       9 RETURN_VALUE   

Non importa quanto sia complesso il valore è, l'assegnazione a una variabile (o dict ingresso, o un campo oggetto) è una singola operazione di memorizzazione atomica.

+0

questo è esattamente quello che volevo controllare .. – gsagrawal

+0

Penso che questa risposta sia ottima. Per riferimento futuro e visitatori, qualcuno (tu? :-)) dovrebbe prendere il tempo e aggiungere una spiegazione dettagliata di ciò che sta accadendo dietro le quinte che porta a questo stato incoerente (incorporando anche le informazioni dell'altra risposta, che 'STORE_FAST (a) 'viene eseguito prima di' STORE_FAST (b) '). –

4

No, l'assegnazione della sequenza non è atomica. Basta dare uno sguardo al codice di byte:

>>> def unpack(): 
     a,b=1,2 

>>> import dis 
>>> dis.dis(unpack) 
    2   0 LOAD_CONST    3 ((1, 2)) 
       3 UNPACK_SEQUENCE   2 
       6 STORE_FAST    0 (a) 
       9 STORE_FAST    1 (b) 
      12 LOAD_CONST    0 (None) 
      15 RETURN_VALUE   

L'assegnazione prende più codici operativi per valutare le tuple e memorizzare il risultato in variabili.

+0

quindi è come questo passaggio contiene 6 operazioni atomiche ?? o questo è di 2 operazioni atomiche – gsagrawal

+1

Una singola istruzione opcode è atomica. Un thread diverso può modificare il valore in considerazione in qualsiasi momento tra 2 codici opzionali. –

Problemi correlati