Такой код. Есть таблица, к которой имеют доступ все потоки, запись редка, и с блокировкой, но чтение должно не знать, что оно в многопоточной среде и должно быть максимально быстрым.
В примере просто читаю в локальную переменную ячейку в массиве. В 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
Как работает перестановка инструкций процессоре, могут ли операции чтения переставляется?, в компиляторе, может ли она переставить местами инструкции или выполнить одну быстрее, или еще какая-то ерунда может произойти?
Если вдруг да, то есть ли какой-то алгоритм способ, техника, или атрибут, который может гарантировать что все на месте