How to increment (add value to) decimal in a thread-safe way?

No. The internal representation of decimal is too complex for modifications to be made with atomic instructions at the CPU level (which is what Interlocked does most of the time, and which is what you are interested in).

When the CPU cannot atomically handle some quantity manual locking is the only option. You get to choose the synchronization primitive (e.g. lock vs a mutex) but that's it.


You can still use InterLocked, but then you have to convert the decimal to an Int64. With the conversion you have to decide how many decimal places you want to preserve for precision. So for example, you want to preserve 4 decimal places, you could do something like this:

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

Be aware that you will lose precision, depending on how many decimal places you would like to preserve. And Decimal.MaxValue is 79,228,162,514,264,337,593,543,950,335 whereas Int64.MaxValue is 9,223,372,036,854,775,807. So very large numbers won't fit. Preserving 4 decimal places, the largest number before the Int64 would overflow is 9,223,372,036,854,775,807 / 10000 = 922,337,203,685,477

I use it this way as numbers here will never go above 1,000,000,000 and I am sure that using Interlocked this way is faster in a Parallel.For loop then using a lock or mutex.


Using lock is not overkill. It is required.

Structure types like System.Decimal are never atomic, it also doesn't fit the native cpu word size. Which is why Interlocked doesn't have an overload for it either.