Самый быстрый способ безопасного чтения содержимого long [], элементы которого изменяются одновременно - PullRequest
0 голосов
/ 23 октября 2018

Если у вас есть

long[] myArray = new long[256];

, чьи элементы меняются несколькими потоками с использованием

Interlocked.Increment(ref myArray[x])

, точно не получится получить снимок myArray за один раз.на данный момент, поскольку одновременно происходят незафиксированные записи, поэтому я не пытаюсь получить это.

Так что мне действительно нужно Volatile.Read каждого элемента, подобного этому, чтобы получить копиюиз всех значений в какой-то момент в прошлом?

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

Поскольку меня не интересует моментальный снимок в какой-то момент времени, устаревшие значения не являются проблемой, но так как 64-битное энергонезависимое чтениене являются атомарными, я боюсь, что следующее может дать мне половину длинного перед инкрементом и половину постинкрементного, что может дать значение, которое никогда не существовало в массиве.

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

Итаквариант Volatile.Read - правильный выбор, учитывая, что я не хочу использовать какую-либо блокировку?

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Если устаревшие значения не являются проблемой для вас, и все, что вам нужно, это атомарное чтение (не упорядоченное), тогда в x64 вы можете просто использовать обычное чтение вместо Volatile.Read.Это может быть выгодно в системах ARM, где энергозависимые операции чтения / записи являются достаточно тяжелыми, поскольку они реализованы с помощью DMB.

Важно Согласно это и , что, вам нужно (собрать и) запустить вашу .Net программу в 64-битном режиме, чтобы это работало:

, если вы запускаете код C # в 64-битной операционной системе в 64-битной системе.битовая версия CLR затем считывает и записывает 64-битные двойные и длинные целые числа, также гарантированно будут атомарными

0 голосов
/ 23 октября 2018

В C # нет такого понятия, как атомарный тип (как вы, вероятно, знаете), есть только атомарные операции.

Процессор Jitter и / или может решить переупорядочить инструкции, поэтому вы правы, если предположите, что вам нужно либо

  • Сериализация доступ с lock
  • Используйте класс Interlocked для записи (и в некоторых случаях для чтения)
  • Объявите переменную volatile (хотя она недоступна в64-битные типы и не применяются к массиву)
  • Или в вашей ситуации используйте Volatile.Read, если вы не возражаете против устаревших значений.

Чтобы ответить на ваш вопроси, не видя ваш код или то, как вы это делаете, ваш подход кажется правильным решением

Volatile.Read Метод

Считывает значениеполе.В системах, которым это требуется, вставляется барьер памяти, который не позволяет процессору переупорядочивать операции с памятью следующим образом: Если после этого метода в коде появляется чтение или запись, процессор не может переместить его до этого метода

...