2013-10-22 3 views

risposta

12

L'utilizzo del blocco non è eccessivo. È richiesto .

I tipi di struttura come System.Decimal non sono mai atomici, inoltre non si adattano alla dimensione della parola della cpu nativa. Ecco perché Interlocked non ha nemmeno un sovraccarico.

3

No. La rappresentazione interna di decimal è troppo complesso per modifiche da apportare con le istruzioni atomiche a livello di CPU (che è quello Interlocked fa la maggior parte del tempo, e che è ciò che siete interessati).

Quando la CPU non può gestire atomicamente una quantità di blocco manuale è l'unica opzione. Puoi scegliere la primitiva di sincronizzazione (ad esempio lock rispetto a un mutex) ma il gioco è fatto.

0

è comunque possibile utilizzare InterLocked, ma poi si deve convertire il decimale in Int64. Con la conversione devi decidere quanti posti decimali vuoi conservare per precisione. Così, per esempio, si desidera conservare posti 4 decimali, si potrebbe fare qualcosa di simile:

 //Declare up front accessible from all threads 
     Int64 totalAmount = 0; 

     //Inside the thread you do this 
     var amount = (Int64)(decimalAmount * 10000); //10.000 is to preserve 4 decimal places 
     Interlocked.Add(ref totalAmount, amount); 

     //After all threads have finished, go back to decimal type. 
     var totalDecimalAmount = totalAmount/10000; 

essere consapevoli del fatto che si perde di precisione, a seconda di quanti posti decimali che si desidera conservare. E Decimal.MaxValue è 79,228,162,514,264,337,593,543,950,335 mentre Int64.MaxValue è 9,223,372,036,854,775,807. Quindi numeri molto grandi non andranno bene. Preservare 4 cifre decimali, il maggior numero prima della Int64 sarebbe traboccare è 9,223,372,036,854,775,807/10000 = 922,337,203,685,477

lo uso così come i numeri qui non potrà mai andare sopra miliardo e sono sicuro che l'utilizzo di Interlocked in questo modo è più veloce in un ciclo Parallel.For poi utilizzando un lock o un mutex.

0

Se non si mente mantenendo il totale come oggetto avvolto decimal, si potrebbe usare questo approccio:

private static object myTotal = 0M; 
static void InterlockedAddTotal(decimal val) { 
    object next; 
    object current; 
    do { 
     current = myTotal; 
     next = val + (decimal)current; 
    } while (Interlocked.CompareExchange(ref myTotal, next, current) != current); 
} 

Sebbene questo approccio non utilizza una serratura, avvolge decimal in un oggetto, che trasporta le sue implicazioni sulla performance. A seconda della situazione, l'uso di un lucchetto potrebbe essere più economico.