Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
Заблокирован

Метод Interlocked.Exchange(Double, Double) не гарантирует одинаковое значение переменной в разных потоках?

20.03.2024, 13:45. Показов 2566. Ответов 48

Студворк — интернет-сервис помощи студентам
Метод Interlocked.Exchange(Double, Double) обеспечивает атомарность операции присвоения нового значения переменной типа Double.
То есть, InterlockedExchange гарантирует, что изменение переменной и возврат ее исходного значения не будут прерваны другими потоками.
Но есть ли гарантия, что данная переменная будет после этого иметь одно и то же значение в разных потоках, в том числе, исполняемых на разных процессорах? Похоже, что нет.
Но если нет, то тогда для обеспечения одинакового значения переменной нужно применять lock?
И тогда, если блокировать код присвоения с помощью lock, то тогда Interlocked.Exchange уже нет смысла использовать?
Правилен ли вывод, что Interlocked.Exchange имеет смысл применять в том случае, когда не нужно, чтобы значение переменной во всех потоках было одинаковым (самым последним)?
А преимущество Interlocked.Exchange по сравнению с блокировкой lock в том, что Interlocked.Exchange не тормозит потоки?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
20.03.2024, 13:45
Ответы с готовыми решениями:

[Error] cannot convert 'double (*)(double)' to 'double' for argument '1' to 'double pow(double, double)'
#include <iostream> #include <math.h> using namespace std; int main () { system("cls"); double x,y; system ("echo...

Ошибки error C2296: -: недопустимо, левый операнд имеет тип "double (__cdecl *)(double,double,double
Думаю из-за polp #include<iostream> #include<cmath> #include<cstdlib> using namespace std; double polp(double af,double...

Написать функцию int Search ( double A[], int n , double x), которая находит в массиве double A[n] элемент, значение которого равно x
Написать функцию int Search ( double A, int n , double x), которая находит в массиве double A элемент, значение которого равно x. Функция...

48
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18242 / 14156 / 5366
Регистрация: 17.03.2014
Сообщений: 28,846
Записей в блоге: 1
20.03.2024, 14:53
Лучший ответ Сообщение было отмечено titan4ik как решение

Решение

Цитата Сообщение от titan4ik Посмотреть сообщение
Но есть ли гарантия, что данная переменная будет после этого иметь одно и то же значение в разных потоках, в том числе, исполняемых на разных процессорах? Похоже, что нет.
По моему это гарантируется если все операция изменения идут через класс Interlocked. Иначе требуется volatile или ручные memory barriers.

Цитата Сообщение от titan4ik Посмотреть сообщение
Но если нет, то тогда для обеспечения одинакового значения переменной нужно применять lock?
С каких пор lock начал давать такие гарантии?

Цитата Сообщение от titan4ik Посмотреть сообщение
И тогда, если блокировать код присвоения с помощью lock, то тогда Interlocked.Exchange уже нет смысла использовать?
Да (но - смотрим выше).

Цитата Сообщение от titan4ik Посмотреть сообщение
Правилен ли вывод, что Interlocked.Exchange имеет смысл применять в том случае, когда не нужно, чтобы значение переменной во всех потоках было одинаковым (самым последним)?
Нет. Interlocked.Exchange имеет смысл применять когда требуется выполнить атомарную операцию с минимальными накладными расходами.

Цитата Сообщение от titan4ik Посмотреть сообщение
А преимущество Interlocked.Exchange по сравнению с блокировкой lock в том, что Interlocked.Exchange не тормозит потоки?
Скорее меньше тормозит чем не тормозит вообще. Такие операции по определению имеют цену. Вопрос только в размере.
1
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,227
20.03.2024, 15:13
Цитата Сообщение от titan4ik Посмотреть сообщение
Правилен ли вывод, что Interlocked.Exchange имеет смысл применять в том случае, когда не нужно, чтобы значение переменной во всех потоках было одинаковым (самым последним)?
Нет. Если есть требование к реализации потокобезопасного lock-free кода, то одним из вариантов может быть как раз Interlocked.Exchange. В официальных доках по методу есть наглядный пример.
1
Заблокирован
20.03.2024, 15:18  [ТС]
Цитата Сообщение от OwenGlendower Посмотреть сообщение
С каких пор lock начал давать такие гарантии?
И в самом деле. с чего это я так решил)
lock тоже просто защищает некий операцию с неким общим ресурсом от вмешательства других потоков.
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Нет. Interlocked.Exchange имеет смысл применять когда требуется выполнить атомарную операцию с минимальными накладными расходами.
Это понятно. Я имел ввиду идею о том, что, обеспечивая атомарность, Interlocked.Exchange не обеспечивает идентичности значений переменной в разных потоках. Но Вы полагаете, что обеспечивает, если все изменения идут через методы Interlocked:
Цитата Сообщение от OwenGlendower Посмотреть сообщение
По моему это гарантируется если все операция изменения идут через класс Interlocked. Иначе требуется volatile или ручные memory barriers.
Надо мне погуглить ещё)
Не нашел пока исчерпывающего и однозначного достоверного источника по этому вопросу.
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,227
20.03.2024, 15:23
Лучший ответ Сообщение было отмечено titan4ik как решение

Решение

Цитата Сообщение от titan4ik Посмотреть сообщение
Я имел ввиду идею о том, что, обеспечивая атомарность, Interlocked.Exchange не обеспечивает идентичности значений переменной в разных потоках.
Вы имели ввиду кэши каждого ядра процессора? Если я правильно понял, то тут работа ведется работа как раз именно с шареной памятью (ведь все Interlocked-методы работают с ключевым словом ref). К тому же, все Interlocked-методы являются в каком-то смысле super-volatile, то есть запрещаются всякого рода reordering-оптимизации в обе стороны у всех методов этого класса.
1
Заблокирован
20.03.2024, 15:26  [ТС]
Цитата Сообщение от IamRain Посмотреть сообщение
Если есть требование к реализации потокобезопасного lock-free кода, то одним из вариантов может быть как раз Interlocked.Exchange. В официальных доках по методу есть наглядный пример.
ОК.
Ну да. Пишут что "The following code example shows a thread-safe resource locking mechanism."
Это я, видать, не дочитал сразу
Сбивают с толка пространные рассуждения в интернете по этому поводу. Пишут так, что можно понять, что это не жёстко определено, а может быть и так и эдак в зависимости от внешнего окружения.

Добавлено через 1 минуту
Цитата Сообщение от IamRain Посмотреть сообщение
Вы имели ввиду кэши каждого ядра процессора?
Ну да, читал об этом.
ОК, я понял, что Interlocked-методы обеспечивают потокобезопасность без всяких оговорок. Спасибо!
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,227
20.03.2024, 15:34
Цитата Сообщение от titan4ik Посмотреть сообщение
Сбивают с толка пространные рассуждения в интернете по этому поводу.
Еще сбивают с толку, что volatile-поля запрещается читать из кэша, я уже дважды слышал такое утверждение. Скорее всего оно верное, но смысл volatile-полей в запрете на reordering-оптимизацию, здравый смысл подсказывает что запрет на чтение из кэша - это предполагаемое поведение, и это предположение должно быть и ежу понятно. То есть акцент делается на совсем других вещах. Это как говорить, что значимые типы хранятся в стеке, а ссылочные - в куче. Немножко правда, но основное отличие - совершенно в другом.
1
Заблокирован
20.03.2024, 15:40  [ТС]
Чтобы вбить последний гвоздь в...
Не будет глупостью такой код в котором некий кусок кода заблокирован с помощью lock, а внутри него некоторые отдельные операции защищены ещё и с помощью методов Interlocked?
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,227
20.03.2024, 15:56
Цитата Сообщение от titan4ik Посмотреть сообщение
Не будет глупостью такой код
Скорее всего будет лишним, а глупостью - это кто как назовет.

Добавлено через 2 минуты
Лучше уж только Interlocked, без всяких lock-ов. Интуитивно кажется легче/быстрее. Если весь упор делать на perf, в моем понимании.
1
Заблокирован
20.03.2024, 16:05  [ТС]
Цитата Сообщение от IamRain Посмотреть сообщение
Если весь упор делать на perf, в моем понимании.
perf - это что такое?
0
20.03.2024, 16:12

Не по теме:

titan4ik, сокращение от performance. Когда много буржуйских буков читаешь, иногда русский эквивалент кажется менее точным и неподходящим, поэтому хочется англоязычную терминологию использовать. К тому же так сильно короче. Это как Solution и Решение.

0
Заблокирован
20.03.2024, 16:17  [ТС]

Не по теме:

ну да, буржуйские лучше, чем калька на русском



Добавлено через 2 минуты
Но как я понял, отличие Interlocked и всяких lock-ов не только в производительности. lock же не обеспечит того, чтобы во всех потоках переменная имела одно значение. Этот же вопрос главный был. Меня конкретно тип Double интересовал.
0
 Аватар для Andrey-MSK
3313 / 2200 / 387
Регистрация: 14.08.2018
Сообщений: 7,404
Записей в блоге: 4
20.03.2024, 16:21
Цитата Сообщение от titan4ik Посмотреть сообщение
lock же не обеспечит того, чтобы во всех потоках переменная имела одно значение.
Тут поможет DI. Пишете сервис, определяете как Singleton и храните в нём что нужно.
1
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,227
20.03.2024, 16:26
Цитата Сообщение от titan4ik Посмотреть сообщение
ock же не обеспечит того, чтобы во всех потоках переменная имела одно значение. Этот же вопрос главный был.
Почему не обеспечит? - обеспечит. Просто это ванильный blocking-примитив из user-space, он быстрее всяких Mutex-ов и прочего, но он все же блокирующий. А блокирующий значит более медленный, и потенциально впустую расходующий потоки.
Если будет high contention (погнали по-полной!), то будут задержки со входом в критическую секцию и будет пустое расходование ресурсов, при spin-based примитивах будет уже быстрее, но будет много холостой работы процессора, и тут уже надо думать что использовать под конкретный сценарий.

Вы слишком рано зациклились на кешах, как мне кажется. Такие вещи надо исследовать benchmark-ами, которые еще надо правильно написать, чтобы увидеть разницу.
1
Заблокирован
20.03.2024, 16:30  [ТС]
Andrey-MSK, в рамках изначальной постановки вопроса (для Double, в частности) я понял, что можно и нужно использовать методы Interlocked.

Добавлено через 3 минуты
Цитата Сообщение от IamRain Посмотреть сообщение
Почему не обеспечит? - обеспечит.
у OwenGlendower, во втором сообщении в этой теме было высказывание, что не обеспечит, если я правильно это понял.
0
 Аватар для IamRain
4693 / 2701 / 734
Регистрация: 02.08.2011
Сообщений: 7,227
20.03.2024, 16:44
Цитата Сообщение от titan4ik Посмотреть сообщение
у OwenGlendower, во втором сообщении в этой теме было высказывание, что не обеспечит, если я правильно это понял.
Это просто детали низкоуровневого кэша, у вас какие-то неправильные сомнения - все примитивы синхронизации как раз были придуманы для того, чтобы обеспечить предсказуемое поведение чтения/записи шареных состояних в многопоточном окружении. Если следовать вашей логике, то раз у нас есть регистровый кэш, то ни один Semaphor/Mutex/Barrier/что-там еще/... нам не поможет, поэтому у нас лапки и это все бесполезно.

Насколько я понимаю, c Interlocked и volatile можно работать.
Вообще рекомендую почитать статейку, старую, но все же это база - C# Memory Model by Igor Istrovsky.
1
Заблокирован
20.03.2024, 20:30  [ТС]
Цитата Сообщение от IamRain Посмотреть сообщение
Вообще рекомендую почитать статейку, старую, но все же это база - C# Memory Model by Igor Istrovsky.
Там ещё вторая часть есть - https://learn.microsoft.com/en... ice-part-2
0
Заблокирован
21.03.2024, 13:48  [ТС]

Не по теме:

Прочитал первую и просмотрел вторую. Мда.
В современном мире, в котором всем управляют менеджеры, которые смотрят в монитор и отвечают вам что-то вроде: "А у меня в компьютере...", всё возможно. Любой, самый нелепый исход. Однажды можно проснуться и узнать, что "в компьютере написано", что вас уже нет. Или - что никогда не было. А как там системы предупреждения о ракетном нападении и автоматического ответа на него? Мда. Ж/Д стрелки и т.п.


В связи с многопоточностью и т.п. появилось конкретное соображение относительно прав собственности и их смены.
Сейчас отменены "Свидетельства о праве собственности". есть только записи в реестре (в компутере). Можно получить выписку из реестра (компутера). При сделках с недвижимостью требуют "свежую" выписку. Но какой бы свежей она ни была, это не гарантирует того, что после получения этой выписки, недвижимость уже была продана.
Предлагаю ввести блокирующую выписку!
То есть, перед сделкой продавец должен получить выписку, которая на определенный срок (например, на 10 дней) блокирует все сделки с этой недвижимостью за исключением продажи данному конкретному покупателю, о чем и будет указано в этой выписке.
0
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
27.03.2024, 02:08
Лучший ответ Сообщение было отмечено titan4ik как решение

Решение

Читал по диагонали, не знаю к чему таки пришли, но рассуждения что Interlocked отменяет необходимость использования volatile по моему скромному мнению неверно.
Для вызова самого Interlocked.Exchange volatile не нужен, потому как все Interlocked методы и так оборудованы необходимым механизмом обеспечивающим работу с наиболее актуальной версией значения переменной, если можно так выразиться)
Для других же мест где производится просто чтение переменной и где необходима гарантия получения наиболее актуального значения, нужен один из приемов который под капотом так или иначе использует Thread.MemoryBarrier().
А именно

1. Обозначение поля как volatile
C#
1
private volatile int HotVar;
Плюсы - никто не забудет использовать нужный прием.
Минусы - все попытки чтения будут включать вызов Thread.MemoryBarrier(), а это доп издержки которые не всегда нужны.

2. Оборачивание чтения в конструкцию lock
C#
1
2
3
4
5
int curVal;
lock(myLock) 
{
   curVal = HotVar;
}
Плюсы - метод рабочий.
Минусы - это как из пушки по воробьям. lock вызывает метод ядра, а это очень дорогая операция (тысячи тактов если не ошибаюсь)

3. Доступ через Volatile.Read
C#
1
var curVal = Volatile.Read(ref HotVar);
Плюсы - полный контроль над происходящим, понятно что происходит.
Минусы - нет.

4. Собственно вызов Thread.MemoryBarrier().
C#
1
2
Thread.MemoryBarrier();
var curVal = HotVar;
Плюсы - полный контроль над происходящим.
Минусы - может ввести в ступор большинство погромистов, повышен риск что непонятный код будет удален после короткого тестирования и подтверждения что "все и так работает нормально".
2
Заблокирован
27.03.2024, 09:10  [ТС]
nicolas2008,
то есть, если расположить способы в таком порядке, что сначала лучшие, то так (?):
№3 - минусов нет
№1 - Минусы - все попытки чтения будут включать вызов Thread.MemoryBarrier(), а это доп издержки которые не всегда нужны.
№4 - Thread.MemoryBarrier(), а это доп издержки которые не всегда нужны и может ввести в ступор большинство погромистов, повышен риск что непонятный код будет удален после короткого тестирования и подтверждения что "все и так работает нормально".
№2 - Минусы - это как из пушки по воробьям. lock вызывает метод ядра, а это очень дорогая операция (тысячи тактов если не ошибаюсь)
---
Тогда лучший рецепт - Interlocked для изменения плюс Volatile.Read для чтения?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.03.2024, 09:10
Помогаю со студенческими работами здесь

Ошибка: error LNK2001: unresolved external symbol "double __cdecl Akk(double,double,double)"
#include <iostream> #include <cmath> using namespace std; double Akk(double x, double y, double z); int main() { int a, b, c; ...

Отметьте 3 ошибочных объявления переменной типа double, Double
Добрый день! Пожалуйста, помогите разобраться. Отметьте 3 ошибочных объявления переменной типа double, Double 1)double d1 = 0.0f;...

Отметьте 3 ошибочных объявления переменной типа double, Double
Добрый день! Пожалуйста, помогите разобраться. Отметьте 3 ошибочных объявления переменной типа double, Double 1)double d1 = 0.0f;...

Перегрузите метод f так, чтобы соответствовала виду static void f (double x, out double y)
ПОМОГИТЕ!! Выдаёт ошибку! До передачи управления из текущего метода выходному параметру "y" должно быть присвоено значение. ...

Перегрузите метод f так, чтобы его сигнатура соответствовала виду static void f (double x, out double y)
Как сделать метод, чтобы он соответствовал заданию? class Program { static double f(double x) { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru