Note. This answer (including two changes already) was given before the question was changed to have a long count . For the current question, instead of Thread.VolatileRead I would use Interlocked.Read , which also had volatile semantics, and also examined the 64-bit reading problem described here and introduced into the question
Atomic reading is guaranteed without blocking, since reading correctly aligned values ββof 32-bit or less, which is your count , is guaranteed to be atomic.
This is different from a 64-bit value, if it started with -1 and was read while another thread was increasing it, it could cause the value to be -1 (happened before the increment), 0 (happened after the increment) or any of 4294967295 or -4294967296 (32 bits written to 0, other 32 bits waiting to be written).
Atomic increment Interlocked.Increment means that the entire increment operation is atomic. Consider the increment conceptually:
- Read the meaning.
- Add a value to the value.
- Enter value.
Then, if x is 54, and one thread tries to increase it, and the other tries to set it to 67, two correct possible values ββare 67 (increment occurs first, then is written) or 68 (assignment happens first, then increases), but the non-atomic increment can lead to 55 (reading increment, assignment 67 occurs, increment writes).
A more general real case: x is 54, and one thread increases and the other decreases. Here the only real result is 54 (one up, then one down or vice versa), but if not atomic, then results 53, 54 and 55 are possible.
If you just want the number that was incremented using atomic input to have the correct code:
private int count; public int Count { get { return Thread.VolatileRead(byref count); } } public void Increment { Interlocked.Increment(count); }
If you want to act on this account, then a stronger lock will be required. This is due to the fact that the thread using the account may become outdated before its completion. In this case, you need to fix everything that worries the account and everything that changes it. Just how it needs to be done (and whether it is important to do it at all) depends on more questions from your use case than can be deduced from your question.
Edit: Oh, you can just lock to force a memory barrier. You can also change the implementation of count to return Thread.VolatileRead(ref count); to ensure that the processor caches are cleared if you intend to remove the lock. It depends on how important the importance of the cache is in this case. (Another alternative is to make count volatile, since then all reads and writes will be volatile. Note that this is not required for Interlocked operations, as they are always unstable.)
Edit 2: In fact, you probably want this mutable read that I am changing the answer above. it you may not care what he offers, but much less likely.