You can atomically update the variable without locking by using Interlocked.CompareExchange until you're successful. This avoids the overhead of locking while ensuring consistency, the following pseudo code should do it, sorry I'm not too familiar with C#.
static void atomic_add(ref int ptr, int addend){
int previous = *ptr;
while(1){
int observed = Interlocked.CompareExchange(ptr, previous+addend, previous);
if(observed == previous){
break;
}else{
previous = observed;
}
}
}
CompareExchange will replace the value at the first argument with the second argument if the value pointed to by the first argument is equal to the third argument, and returns the value in memory at ptr when CompareExchange was called. If the value returned by compare exchange is the same as the previous value observed at ptr then the value was successfully updated and the loop breaks, otherwise, the value in the pointer changed since its last read and previous is updated and we try again.
From what I've read Interlocked.CompareExchange exists for only int32, floats, and objects (though not sure if that one would be completely lockless?). I imagine it would work for wider values on 64 bit platforms, but I have nothing to back that up.