Задать вопрос
@Nimus2000

Как прочесть без блокировок в многопоточном приложение 16 байт структурное значение?

Такой код. Есть таблица, к которой имеют доступ все потоки, запись редка, и с блокировкой, но чтение должно не знать, что оно в многопоточной среде и должно быть максимально быстрым.
В примере просто читаю в локальную переменную ячейку в массиве. В local всегда должна быть одна версия пары value,key. Один поток может успеть перезапись value или допусти поток прервется, где-то между чтением value и key.
Верна ли логика, что что бы не случилось в локальной переменной будет одна версия, либо будет из 2 версий, но не совпадет key. То есть если value уже прочлось первым, то значит value всегда старой версии, значит key будет либо из старой версии прочитан, либо из новой, но уже не совпадет.

Note[] cache;
   struct Note
   {
       public Object value;
       public Object key;
   }

 var  local =cache[fastHash];
   if(localt.key==key){
         return local.value;
}
...

Запись с блокировкой, и можно еще System.Threading.Thread.SpinWait(10); между записью полей, с MemoryFence вставить. Тогда же по логике, всегда тот кто читает прочтет одну версию?
Такой асемблерный код генерится, если rax совпал, а его чтение было вторым, значит и до должно быть с той же версии
L0024: shl rcx, 4
    L0028: lea rax, [rax+rcx+0x10]
    L002d: mov rcx, [rax]                  
    L0030: mov rax, [rax+8]
    L0034: xor edx, edx
    L0036: cmp rax, rsi

Как работает перестановка инструкций процессоре, могут ли операции чтения переставляется?, в компиляторе, может ли она переставить местами инструкции или выполнить одну быстрее, или еще какая-то ерунда может произойти?
Если вдруг да, то есть ли какой-то алгоритм способ, техника, или атрибут, который может гарантировать что все на месте
  • Вопрос задан
  • 39 просмотров
Подписаться 1 Простой Комментировать
Помогут разобраться в теме Все курсы
  • Stepik
    PRO C#. Профессия "Backend разработчик"
    4 месяца
    Далее
  • Merion Academy
    C# разработчик с нуля
    4 месяца
    Далее
  • XYZ School
    C# для разработки игр
    5 месяцев
    Далее
Пригласить эксперта
Ответы на вопрос 1
У тебя тут прям книжный пример гонки.
Используй System.Threding.Interlocked, чтобы гарантировать порядок чтения/записи.
MemoryFence очень редко когда нужен - это раз.
Его нужно использовать и на стороне чтения тоже - это два.


могут ли операции чтения переставляется

Могут и переставляться, и кэшироваться, и удаляться "лишние" чтения по мнению компилятора, если не обмазываться атомиками.

но чтение должно не знать, что оно в многопоточной среде и должно быть максимально быстрым.

Вспоминается анекдот:

Сколько будет 453 * 774?
954755 - ответил без раздумий.
Но это же не правильно...
Зато быстро!



Такой асемблерный код генерится

Завтра, когда обновиться компилятор, рантайм, JIT соберёт другую статистику, программа будет запущена на другом компьютере, меркурий будет в Козероге - сгенерится другой код.


Если вдруг да, то есть ли какой-то алгоритм способ, техника, или атрибут, который может гарантировать что все на месте

Interlocked либо уже готовые структуры типа ConcurrentDictionary.

Если добавить контекста:
1. Сколько потоков пишут
2. Сколько потоков читают
3. Как вообще эти данные используются

То можно будет уже говорить об оптимальном решении.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы