Подтвердить что ты не робот

Где InterlockedRead?

Win32 api имеет набор функций InterlockedXXX для атомарного и синхронного управления простыми переменными, однако, как представляется, нет функции InterlockedRead, чтобы просто получить значение переменной. Почему?

MSDN говорит, что "простые чтения и записи в правильно выровненные 32-битные переменные являются атомарными операциями", но добавляет, что "Однако доступ не гарантируется для синхронизации", что означает, как я понимаю, что простой операция чтения переменной может иметь место, а другая, скажем, операция InterlockedAdd. Итак, почему нет функции блокировки для чтения переменной?

Я думаю, что значение можно прочитать как результат InterlockedAdd-ing zero, но это не похоже на правильный путь.

4b9b3361

Ответ 1

Обычным способом реализации этого является использование операции сравнения (например, InterlockedCompareExchange64), где оба значения одинаковы. У меня есть подозрительное подозрение, что это может быть сделано более эффективно, чем добавление 0 по какой-то причине, но у меня нет никаких доказательств, чтобы поддержать это.

Интересно, что .NET Interlocked класс не получил Read до .NET 2.0. Я считаю, что Interlocked.Read реализуется с помощью Interlocked.CompareExchange. (Обратите внимание, что документация для Interlocked.Read поражает меня как несколько вводящую в заблуждение - она ​​говорит об атомарности, но не волатильности, что означает что-то очень специфичное для .NET. Я не уверен, что модель памяти Win32 гарантирует видимость новых записанных значений из другого потока, если что угодно.)

Ответ 2

Я думаю, что ваша интерпретация "не синхронизирована" неверна. Простые чтения являются атомарными, но вы должны сами заботиться о переупорядочении и проблемах с памятью. Первый обрабатывается с помощью инструкций по заборам в соответствующих местах, последний не является проблемой с чтением (но потенциальная одновременная запись должна обеспечивать надлежащую видимость, которую должны выполнять функции блокировки, если они соответствуют инструкциям ASM LOCKED).

Ответ 3

Суть всего этого обсуждения - правильное выравнивание, которое выделено в разделе я ххх в разделе "12.6.2 Alignment":

Built-in datatypes shall be properly aligned, which is defined as follows:
• 1-byte, 2-byte, and 4-byte data is properly aligned when it is stored at
  a 1-byte, 2-byte, or 4-byte boundary, respectively.
• 8-byte data is properly aligned when it is stored on the same boundary
  required by the underlying hardware for atomic access to a native int.

В принципе, все 32-битные значения имеют требуемое выравнивание, а на 64-битной платформе 64-битные значения также имеют требуемое выравнивание.

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

С этой целью цель класса Interlocked заключается в предоставлении операций, которые (перефразировать) можно наблюдать только в состоянии "до" или "после". Операции с блокировкой обычно вызывают озабоченность при изменении памяти (как правило, с помощью некоторого нетривиального способа сравнения). Поскольку найденная вами статья MSDN указывает, операции чтения (при правильной выровненности) могут считаться атомарными в любое время без дополнительных мер предосторожности.

Существуют и другие соображения при работе с операциями чтения:

  • На современных процессорах, хотя чтение может быть атомарным, оно также может возвращать неправильное значение из старого кэша где-то... вот где вам может понадобиться сделать поле "volatile", чтобы получить ожидаемое поведение
  • Если вы имеете дело с 64-битным значением на 32-разрядном оборудовании, вам может потребоваться использовать операцию Interlocked.Read, чтобы гарантировать, что все 64-битное значение считывается в одной атомной операции (иначе это может быть выполнено как 2 отдельных 32-битных чтения, которые могут быть с обеих сторон обновления памяти).
  • Переупорядочение ваших чтений/записей может привести к тому, что вы не получите ожидаемое значение; в этом случае может потребоваться некоторый барьер памяти (явный или с помощью операций класса Interlocked)

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