2015-03-04 15 views
15
public static int Add(ref int location1,int value) 

Stavo cercando di utilizzare il metodo Interlocked.Add (ref int location1, int value) per aggiungere a un numero in modo atomico in uno scenario multi-threading. Ma mi sono fatto una domanda: perché il metodo restituisce nuovamente il valore location1? Invece potremmo usare direttamente la variabile che viene passata come "ref".Perché il metodo Interlocked.Add() deve restituire un valore?

Alcuni pseudo codice qui sotto:

int a = 6; 
int b = 7; 

// some thing else 

Interlocked.Add(ref a, b); 

// Use the variable 'a' here. 
+3

[Se avete intenzione di utilizzare un'operazione interbloccato per generare un valore unico, è necessario utilizzare prima che sia andato] (http://blogs.msdn.com/b /oldnewthing/archive/2013/04/25/10413997.aspx). – GSerg

+1

Consiglierei di leggere il modello di memoria C++ 11 e perché ha tutti i piccoli dettagli che ha inserito. Non è C# (C# è venuto prima del modello di memoria C++ 11), ma fa un ottimo lavoro nel mostrare quanto siano incredibilmente intuitive le operazioni atomiche a meno che non comprendiate alcune delle limitazioni dell'hardware con cui le operazioni atomiche sono progettate per funzionare. Se non vomiti leggendo su MEMORY_ORDER_CONSUME e kill_dependency, sei pronto per fare operazioni atomiche (ho ancora una piccola bile nella parte posteriore della mia gola, me stesso). –

+6

Seguitelo con qualcosa di specifico per C# come https://msdn.microsoft.com/en-us/magazine/jj863136.aspx. I due approfondimenti più importanti che posso darti sono (1) nel momento in cui inizi a programmare in multithreading con memoria condivisa, devi cambiare il tuo atteggiamento da "i valori delle variabili sono stabili finché qualcosa li fa cambiare" a "i valori delle variabili sono costantemente cambiando a meno che qualcosa li mantenga uguali ", e (2) semplicemente non capisci queste cose abbastanza bene da scrivere programmi privi di bug. Più imparo sul threading, meno sono sicuro di me che sto facendo bene. –

risposta

31

Poiché la variabile ref a potrebbe cambiare "nuovo" prima Interlocked rendimenti (o anche dopo ritorna e prima di utilizzare a). La funzione restituisce invece il valore calcolato.

Esempio:

int a = 5; 

// on thread 1 
int b = Interlocked.Add(ref a, 5); // b = 10 

// on thread 2, at the same time 
int c = Interlocked.Add(ref a, 5); // c = 15 

// on thread 1 
Thread.Sleep(1000); // so we are "sure" thread 2 executed 
Thread.MemoryBarrier(); // just to be sure we are really reading a 
bool x1 = (b == 10); // true 
bool x2 = (a == 15); // true 
Problemi correlati