2016-04-07 47 views
6

Sto cercando di imparare e comprendere meglio il multithreading, ma sono rimasto bloccato dal comportamento delle funzioni atomiche come fetch-and-add. Nel caso specifico di fetch-and-add, è a mia conoscenza che un valore (diciamo x che attualmente è uguale a 5) è aggiunto a un valore di incremento (diciamo 3), la somma risultante (8) viene scritta in x posto in memoria, tuttavia viene restituito il vecchio valore (5).Perché le operazioni atomiche come fetch-and-add restituiscono il vecchio valore della variabile che viene modificata?

Esistono molte altre funzioni simili in luoghi diversi (come le funzioni atomiche di OpenGL, gli oggetti Atomic di Java e molte altre aree) che si comportano in questo modo. Ma quello che non capisco è perché un posto nel codice vorrebbe scrivere in memoria e tuttavia restituire il valore che voleva modificare in primo luogo. Qualcuno può aiutare a far luce su questo?

risposta

2

Ad ampliare la risposta di Sergey ...

guardo fetch-e-add di essere qualcosa di simile a un semaforo; tranne la chiamata fetch-and-add rende tutto un'operazione atomica. Ecco un esempio di un algoritmo che mostra l'uso del valore originale: http://research.omicsgroup.org/index.php/Ticket_lock

+0

Questo è stato un articolo incredibilmente utile da leggere. Grazie, Sergey e Dimitar così tanto per l'aiuto e gli esempi! – hashahid

3

La risposta è molto semplice. La natura delle funzioni atomiche è che modificano (incrementano in questo caso) il valore attuale al momento dell'esecuzione che potrebbe essere diverso dal valore come lo sapeva il tuo codice.

esempio:

x = 5; // x is global 
y = atomically_increment(x); 
// what is y? 

Ora, se x è accaduto a essere cambiato 5-6 a destra prima di incremento in realtà ha avuto luogo, y sarebbe pari a 6, e x a 9.

1

Fetch- e-aggiungere istruzioni o operazioni (come x86's XADD) salvarti dal problema di fare un ciclo CAS e fornire un valore iniziale previsto.

Tuttavia, ciò significa anche che nel codice, dopo che il recupero e l'aggiunta ha avuto esito positivo, non si sa a quale valore è stato aggiunto l'incremento e sotto pesante conflitto, leggendo il valore appena prima del recupero e dell'aggiunta a potrebbe essere ancora lontano dalla verità. Ecco perché restituire il vecchio o il nuovo valore come risultato del recupero e dell'aggiunta atomici è molto utile.

Ad esempio, Aeron utilizza il valore restituito da fetch-and-add per determinare se deve ruotare il suo buffer (vedere https://youtu.be/eKVpea51tvo?t=31m54s).