Fastest way to safely read contents of long[] whose elements are changed concurrently

為{幸葍}努か 提交于 2019-12-10 17:44:35

问题


When you have a

long[] myArray = new long[256];

whose items are changed by multiple threads using

Interlocked.Increment(ref myArray[x])

it sure won't be possible to get a snapshot of myArray at one point in time, as there are non-locked writes going on concurrently, so I'm not trying to get that.

So do I really have to Volatile.Read of every single element like this to get a copy of all values at some point in the past?

long[] copy = new long[256];
for (int i = 0; i < 256; i++)
    copy[i] = Volatile.Read(ref myArray[i]);

As I'm not interested in a snapshot at one point in time, stale values are not a problem, but as 64-bit non-volatile reads are not atomic, I fear that the following may give me a pre-increment half of a long, and a post-increment half, which may give a value that never existed in the array.

long[] copy = new long[256];
for (int i = 0; i < 256; i++)
    copy[i] = myArray[i];

So is the Volatile.Read variant the proper choice, given I don't want to use any locking?


回答1:


If stale values is not an issue for you and all you need is atomic read (not ordered one) then on x64 you can just use plain read instead of Volatile.Read. It can be beneficial on on ARM systems where volatile reads/writes are fairly heavyweight as they are implemented with DMB.

Important According to this and that, you need to (build and) run your .Net program in 64-bit mode for this to work:

if you are running C# code on a 64 bit operating system in a 64 bit version of the CLR then reads and writes of 64 bit doubles and long integers are also guaranteed to be atomic




回答2:


There are no such thing as an atomic type in C# (as you probably know), there are only atomic operations.

The Jitter and/or Processor can decide to reorder instructions, so you are correct in assuming you either need to

  • Serialize access with lock
  • Use the Interlocked class for writes (and in some cases reads)
  • Declare the variable volatile (though its not available on a 64 bit types, and doesn't apply to an array)
  • Or in your situation use Volatile.Read if you don't mind stale values.

To answer your question, and without seeing your code or how you are threading this, your approach seems like the right solution

Volatile.Read Method

Reads the value of a field. On systems that require it, inserts a memory barrier that prevents the processor from reordering memory operations as follows: If a read or write appears after this method in the code, the processor cannot move it before this method



来源:https://stackoverflow.com/questions/52939887/fastest-way-to-safely-read-contents-of-long-whose-elements-are-changed-concurr

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