Are basic arithmetic operations in C# atomic

随声附和 提交于 2019-12-31 00:43:14

问题


Are the basic arithmetic operations Thread safe?

For example, if there is ++ operation on a global variable, which will be modified from different threads, is it necessary to a lock around it?

For example

void MyThread() // can have many running instances
{
    aGlobal++;
}

or should it be

void MyThread()
{
    lock( lockerObj)
    {
        aGlobal++;
    }
}

回答1:


The spec sums it up very well. Section 5.5, "Atomicity of variable references":

Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types. In addition, reads and writes of enum types with an underlying type in the previous list are also atomic. Reads and writes of other types, including long, ulong, double, and decimal, as well as user-defined types, are not guaranteed to be atomic. Aside from the library functions designed for that purpose, there is no guarantee of atomic read-modify-write, such as in the case of increment or decrement.

Conclusions:

  • Independent reads/writes are atomic (but only for some data types)
  • Read/modify/write (such as i++) is never atomic
  • You can use the Interlocked class methods to achieve atomicity when it's not already guaranteed

In cases where Interlocked functionality is not enough there is no other option than to use a synchronization primitive, such as Monitor.Enter (which the compiler also exposes through the lock statement).




回答2:


Reads and writes independently are atomic on most types (not the longer types, usually 64bit+). But what you want is to read, change, then write atomically - this is definitely not atomic.

If you need to increment a value, there is the System.Threading.Interlocked class with static Increment and Decrement actions.

If you need to do more complex sums, then synchronisation using lock or another construct is the only way. That or make things immutable as in messaging systems so you don't get any shared data access issues, but this usually isn't attainable unless designed for upfront.




回答3:


Neither ... you should go for System.Threading.Interlocked.Increment(ref int location) instead. This is lock-free as it ensures that the processor executes the read and the write (instructions - which are atomic) in exactly the wanted order - whereas not using System.Threading.Interlocked.Increment offers the opportunity to the processor to reorder instructions.

Doing the sledgehammer (or having no other possiblity, as you may be doing a heavy amount of operations), you can also use lock - but even in these scenarios I would rather go for System.Threading.ReaderWriterLockSlim instead.

btw - a nice read!



来源:https://stackoverflow.com/questions/10530337/are-basic-arithmetic-operations-in-c-sharp-atomic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!