Volatile.Read перед CompareExchange
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 17.11.21 07:27
Оценка:
Мой вопрос наверное тут уже 100500 раз перетёрт, но что-то явного обсуждения найти не могу...

Все время писал такой код:

if(Object.ReferenceEquals(m_pointer,null))
{
 Interlocked.CompareExchange(ref m_pointer, new TData(), null);
}

Debug.Assert(!Object.ReferenceEquals(m_pointer,null));

return m_pointer;

И пока (на интеле) проблем не было.

Недавно узрел код типа такого:

var tmp=Volatile.Read(ref m_pointer);

if(!Object.ReferenceEquals(tmp,null))
{
 Debug.Assert(!Object.ReferenceEquals(m_pointer,null));

 return tmp;
}

Interlocked.CompareExchange(ref m_pointer, new TData(), null);

return m_pointer;


Оригинал. К нему есть другие, дополнительные вопросы...

Я так понимаю, в tmp попадает последнее значение m_pointer, которое могло быть сделано где-то снаружи на другом процессоре.

То есть, грубо говоря, Volatile.Read заставляет все процессоры проверить и сбросить свои кэши в основную память и только потом читает m_pointer.

---
И меня терзают смутные сомнения.

Мой (первый) вариант хуже тем, что могут быть левые создания TData, которые будут отброшены. Эти "промахи" будут только на стадии инициализации программы.

"Левые" создания могут быть и во втором варианте. Но реже. Поскольку здесь, перед сравнением с null, происходит синхронизация. Но эта синхронизация выполняется каждый раз, на протяжении всего времени функционирования программы. Так?

То есть второй вариант, формально, в круглосуточно работающих программах, хуже?

Или в первом варианте есть какой-то скрытый косяк, из за которого он отработает не так, как ожидается? Но если он есть, то тогда он есть и во втором варианте. Просто реже проявляется...

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

Спасибо за то, что дочитали до конца
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Отредактировано 17.11.2021 8:06 DDDX . Предыдущая версия . Еще …
Отредактировано 17.11.2021 7:52 DDDX . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.