Я лудильщик - в этом нет сомнений. По этой причине (и мало по какой другой) я недавно провел небольшой эксперимент, чтобы подтвердить свои подозрения, что запись в struct
не является атомарной операцией, что означает, что так называемый "неизменяемый" тип значения, который пытается обеспечить соблюдение определенных ограничений, гипотетически может не достичь своей цели.
Я написал статью в блоге об этом, используя следующий тип в качестве иллюстрации:
struct SolidStruct
{
public SolidStruct(int value)
{
X = Y = Z = value;
}
public readonly int X;
public readonly int Y;
public readonly int Z;
}
Хотя приведенный выше выглядит как тип, для которого никогда не может быть истинным, что X ! = Y
или Y != Z
, на самом деле это может произойти, если значение находится "в середине присваивания" в то же время, когда оно копируется в другое место отдельным потоком.
Ладно, большое дело. Любопытство и не более того. Но потом у меня возникла догадка: мой 64-битный процессор должен на самом деле уметь копировать 64 бита атомарно, верно? Так что если я избавлюсь от Z
и ограничусь X
и Y
? Это всего 64 бита; должно быть возможно перезаписать их за один шаг.
Конечно, это сработало. (Я понимаю, что некоторые из вас сейчас, вероятно, нахмурили брови, думая: Да, да. Как это вообще интересно? Пошутите). Конечно, я понятия не имею, гарантировано это или нет, учитывая мою систему. Я почти ничего не знаю о регистрах, промахах кэша и т.д. (я буквально просто пересказываю услышанные термины, не понимая их значения); так что на данный момент все это для меня "черный ящик".
Следующее, что я попробовал - опять же, просто по наитию - это структура, состоящая из 32 бит, использующая 2 коротких
поля. Это, казалось, также демонстрировало "атомарную присваиваемость". Но затем я попробовал 24-битную структуру, используя 3 байтовых
поля: не получилось.
Внезапно структура снова оказалась восприимчивой к копиям "среднего назначения".
Уменьшение до 16 бит с 2 байтовыми
полями: снова атомарно!
Может ли кто-нибудь объяснить мне, почему это так? Я слышал об "упаковке битов", "расположении кэш-линий", "выравнивании" и т.д., но опять же, я не знаю, что все это значит, и имеет ли это значение в данном случае. Но я чувствую, что вижу закономерность, не имея возможности точно сказать, в чем она заключается; ясность была бы очень признательна.