Синхронизация доступа к переменным типа bool
От: FrozenHeart  
Дата: 29.03.14 18:31
Оценка:
Приветствую.

Не так давно разошлись с коллегой во мнениях касательно одного вопроса. Он не считает необходимым синхронизировать доступ к переменной типа bool, когда для неё имеется несколько reader'ов / writer'ов в разных потоках, аргументируя это тем, что операции над переменными подобных типов всё равно выполнятся атомарно и без каких-либо сайд-эффектов на используемых нами платформах. Пишем строго x86 под Windows, код компилируем только в MSVC. Мне такой подход, честно говоря, не по вкусу -- я в любом случае стараюсь использовать std::atomic или какие-нибудь примитивы синхронизации. А что по этому поводу думаете Вы?
avalon/1.0.434
Re: Синхронизация доступа к переменным типа bool
От: uzhas Ниоткуда  
Дата: 29.03.14 19:28
Оценка: 2 (1)
Здравствуйте, FrozenHeart, Вы писали:

FH>А что по этому поводу думаете Вы?


я бы volatile навесил и не парился. собственно, так и делаю =)
Re: Синхронизация доступа к переменным типа bool
От: wander  
Дата: 29.03.14 19:35
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

FH>А что по этому поводу думаете Вы?

У нас на данный момент идет разработка ПО сразу под 3 аппаратные платформы и 4 ОС. Раньше было и того больше, включая некоторые экзотические машинки. Поэтому лично мне такое его отношение кажется дикостью. Если писать на VS и только под x86, то можно и уповать какие-то свойства платформы, но что будет, если завтра нужно будет портировать проект на *nix или на mac или еще куда?
В любом случае нет никакой гарантии атомарности операций над переменными базовых типов, независимо от того насколько мал их размер в байтах.
Re[2]: Синхронизация доступа к переменным типа bool
От: FrozenHeart  
Дата: 29.03.14 19:56
Оценка:
u> я бы volatile навесил и не парился. собственно, так и делаю =)

А volatile-тот тут при чём? По стандарту он как бы не более, чем намёк компилятору на тему того, что к данному объекту не стоит применять никаких хитроумных оптимизаций. Чем он тут поможет?
avalon/1.0.434
Re[2]: Синхронизация доступа к переменным типа bool
От: FrozenHeart  
Дата: 29.03.14 20:02
Оценка:
w> У нас на данный момент идет разработка ПО сразу под 3 аппаратные платформы и 4 ОС. Раньше было и того больше, включая некоторые экзотические машинки. Поэтому лично мне такое его отношение кажется дикостью. Если писать на VS и только под x86, то можно и уповать какие-то свойства платформы, но что будет, если завтра нужно будет портировать проект на *nix или на mac или еще куда?

Согласен.
avalon/1.0.434
Re: Синхронизация доступа к переменным типа bool
От: tdiff  
Дата: 29.03.14 20:05
Оценка: 1 (1)
Здравствуйте, FrozenHeart, Вы писали:

FH>Приветствую.


FH>Не так давно разошлись с коллегой во мнениях касательно одного вопроса. Он не считает необходимым синхронизировать доступ к переменной типа bool, когда для неё имеется несколько reader'ов / writer'ов в разных потоках, аргументируя это тем, что операции над переменными подобных типов всё равно выполнятся атомарно и без каких-либо сайд-эффектов на используемых нами платформах. Пишем строго x86 под Windows, код компилируем только в MSVC. Мне такой подход, честно говоря, не по вкусу -- я в любом случае стараюсь использовать std::atomic или какие-нибудь примитивы синхронизации. А что по этому поводу думаете Вы?


Вон мы в соседней теме
Автор: tdiff
Дата: 28.03.14
как раз обсуждали, что для защиты от разных возможных опасностей всегда надо использовать примитивы синхронизации, не важно, bool это или нет.
Re[3]: Синхронизация доступа к переменным типа bool
От: watchmaker  
Дата: 29.03.14 20:12
Оценка: 6 (2) +1
Здравствуйте, FrozenHeart, Вы писали:

u>> я бы volatile навесил и не парился. собственно, так и делаю =)


FH>А volatile-тот тут при чём? По стандарту он как бы не более, чем намёк компилятору на тему того, что к данному объекту не стоит применять никаких хитроумных оптимизаций.

Не намёк, а требование. И не хитрых оптимизаций, а самых базовых.

FH>Чем он тут поможет?

Собственно, тут важно, что volatile отключит кеширование значения переменной (в регистрах, например) — это одна из самый простейших и полезнейших техник в распоряжении компилятора. Но в то же время кеширование и ломает многопоторчные программы — разные нити исполнения начинают видеть разные значения переменной из-за потери когерентности.

Ну и если рассматривать x86, то volatile bool в принципе, действительно, оказывается достаточно, и можно обойтись без атомарных типов и без внешних средств синхронизации.
Re[4]: Синхронизация доступа к переменным типа bool
От: FrozenHeart  
Дата: 30.03.14 07:00
Оценка:
w> Не намёк, а требование. И не хитрых оптимизаций, а самых базовых.

ISO/IEC 14882:2011

7.1.6.1 The cv-qualifiers [dcl.type.cv]

7 [Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object
because the value of the object might be changed by means undetectable by an implementation. See 1.9 for
detailed semantics. In general, the semantics of volatile are intended to be the same in C ++ as they are
in C. —end note ]


Я перевожу "hint" как "намёк".
avalon/1.0.434
Re[5]: Синхронизация доступа к переменным типа bool
От: watchmaker  
Дата: 30.03.14 11:59
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

w>> Не намёк, а требование. И не хитрых оптимизаций, а самых базовых.


FH>ISO/IEC 14882:2011

FH>

7.1.6.1 The cv-qualifiers [dcl.type.cv]


FH>Я перевожу "hint" как "намёк".


Ну ты и нашел что цитировать :)
Смотри в начало стандарта: program execution и observable behavior. Любая реализация может делать что угодно если её наблюдаемое поведение такое же как и у абстрактной машины, описанной во всё остальном стандарте. И не может делать ничего такого, что нарушает наблюдаемое поведение. Доступ к volatile — наблюдаемое поведение.

Можешь в старом стандарте, например, ещё об этом почитать, там вообще всё кратко:

The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.

(В современном же стандарте к этому тексту просто добавились сигналы, да связанные с легализованной многопоточностью операции)
И компилятор может сделать с твоим кодом всё что угодно, хоть выкинуть его, если сумеет обеспечить тот же порядок доступа к volatile и I/O. Другое дело, делать преобразования над кодом с сохранением таких инвариантов довольно сложно в общем случае, и поэтому большинство компиляторов не отходят далеко от описанной абстрактной машины.
Re[3]: Синхронизация доступа к переменным типа bool
От: uzhas Ниоткуда  
Дата: 30.03.14 20:06
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

FH>А volatile-тот тут при чём? По стандарту


тебе шашечки или ехать? сам же написал "Пишем строго x86 под Windows, код компилируем только в MSVC". в этом случае не стандарт надо открывать, а msdn
Re: Синхронизация доступа к переменным типа bool
От: andrey.desman  
Дата: 30.03.14 21:11
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

FH>А что по этому поводу думаете Вы?


Думаю, что он прав. У булевского типа есть ровно два значения, и в условиях гонки, какого бы ни было внутреннее представление типа, ты получишь ровно один из двух возможных вариантов. При приведении к int компилятор обязан выдать либо 0, либо 1, хотя тут возможны нюансы из-за UB, если он присутствует.
На практике же, на всех известных мне платформах (x86, arm, mips, powerpc) это будет работать. Я бы не парился.
И еще, на тех же платформах даже int атомарен, если имеет правильное выравнивание.
Re: Синхронизация доступа к переменным типа bool
От: okman Беларусь https://searchinform.ru/
Дата: 31.03.14 05:36
Оценка: 10 (1)
Здравствуйте, FrozenHeart, Вы писали:

FH>А что по этому поводу думаете Вы?


Придерживаюсь подхода Вашего коллеги.

В первую очередь потому, что использую компилятор стандарта до C++11, в котором ни
слова не говорится про потоки и характерные проблемы многопоточности (VC++9).
То есть, уповать на какие-то рекомендации стандарта невозможно — их просто нет, и
приходится довольствоваться тем, что называют compiler-specific. Но если пишем только
под Windows, а платформа и компилятор дают определенные гарантии на этот счет, то
почему бы ими не воспользоваться ? В Visual C++ и strtok можно дергать из разных
потоков, и читать объекты стандартной библиотеки и STL. Хотя "по стандарту" нельзя.

"Боякам" (в хорошем смысле этого слова), опасающимся проблем при переходе на другой
компилятор, можно посоветовать сделать врапперы или макросы а-ля BOOST_COMPILER_FENCE,
расширяющиеся в нужную реализацию под нужное окружение.

Городить везде синхронизацию только потому, что "так надо", в моем понимании точно не стоит.
Re: Синхронизация доступа к переменным типа bool
От: MasterZiv СССР  
Дата: 31.03.14 08:42
Оценка:
On 29.03.2014 22:31, FrozenHeart wrote:

> Не так давно разошлись с коллегой во мнениях касательно одного вопроса.

> Он не считает необходимым синхронизировать доступ к переменной типа
> bool, когда для неё имеется несколько reader'ов / writer'ов в разных
> потоках, аргументируя это тем, что операции над переменными подобных
> типов всё равно выполнятся атомарно и без каких-либо сайд-эффектов на
> используемых нами платформах. Пишем строго x86 под Windows, код
> компилируем только в MSVC. Мне такой подход, честно говоря, не по вкусу
> -- я в любом случае стараюсь использовать std::atomic или какие-нибудь
> примитивы синхронизации. А что по этому поводу думаете Вы?

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

Я даже не хочу обсуждать проблему, атомарен ли доступ к bool или нет.
Главное другое -- нет причин экономить на доступе к переменной, а если
они у вас есть -- скорее всего, у вас что-то не так с архитектурой.

Синхронизировать доступ, естественно, надо, до тех пор, пока у вас нет
гарантий атомарного доступа со стороны спецификации API или стандарта
или какой-то библиотеки.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Синхронизация доступа к переменным типа bool
От: MasterZiv СССР  
Дата: 31.03.14 08:45
Оценка:
On 31.03.2014 09:36, okman wrote:

> Городить везде синхронизацию только потому, что "так надо", в моем

> понимании точно не стоит.

А в чём проблема-то нагородить? что заставляет НЕ делать так, как "надо"
? Почему все знают, как надо, но как доходит до дела, включают какой-то
другой ум и "как надо" не делают ?
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Синхронизация доступа к переменным типа bool
От: saf_e  
Дата: 31.03.14 09:54
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>On 31.03.2014 09:36, okman wrote:


>> Городить везде синхронизацию только потому, что "так надо", в моем

>> понимании точно не стоит.

MZ>А в чём проблема-то нагородить? что заставляет НЕ делать так, как "надо"

MZ>? Почему все знают, как надо, но как доходит до дела, включают какой-то
MZ>другой ум и "как надо" не делают ?

http://insidecpp.ru/antipatterns/premature_pessimization/
Re[2]: Синхронизация доступа к переменным типа bool
От: Mr.Delphist  
Дата: 31.03.14 10:29
Оценка:
Здравствуйте, andrey.desman, Вы писали:

AD>Здравствуйте, FrozenHeart, Вы писали:


FH>>А что по этому поводу думаете Вы?


AD>Думаю, что он прав. У булевского типа есть ровно два значения, и в условиях гонки, какого бы ни было внутреннее представление типа, ты получишь ровно один из двух возможных вариантов. При приведении к int компилятор обязан выдать либо 0, либо 1, хотя тут возможны нюансы из-за UB, если он присутствует.


Ну, с гонкой у атомарных операций всё в порядке, согласен. Но что скажете насчёт реордеринга? Тут атомарность никак не спасёт, если компилятор переставит data flow.
Re: Синхронизация доступа к переменным типа bool
От: Mr.Delphist  
Дата: 31.03.14 10:35
Оценка:
Здравствуйте, FrozenHeart, Вы писали:

FH>Приветствую.


FH>Не так давно разошлись с коллегой во мнениях касательно одного вопроса. Он не считает необходимым синхронизировать доступ к переменной типа bool, когда для неё имеется несколько reader'ов / writer'ов в разных потоках, аргументируя это тем, что операции над переменными подобных типов всё равно выполнятся атомарно и без каких-либо сайд-эффектов на используемых нами платформах. Пишем строго x86 под Windows, код компилируем только в MSVC. Мне такой подход, честно говоря, не по вкусу -- я в любом случае стараюсь использовать std::atomic или какие-нибудь примитивы синхронизации. А что по этому поводу думаете Вы?


Если мьютекс — это единственный примитив синхронизации, который знает сей коллега, то проблема явно не в компиляторе
Любое средство не является серебряной пулей: в одном случае и data race не помешает, а в другом — любой чих на несинхронизированную переменную обвалит мировую экономику (утрирую, конечно — но всё же).
Re[3]: Синхронизация доступа к переменным типа bool
От: enji  
Дата: 31.03.14 12:40
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>Ну, с гонкой у атомарных операций всё в порядке, согласен. Но что скажете насчёт реордеринга? Тут атомарность никак не спасёт, если компилятор переставит data flow.


Компилятор этого не сделает — volatile. Вот процессор при исполнении инструкций — может. Но где-то я читал, что при работе с volatile msvc вставляет дополнительные инструции для процессора
Re[4]: Синхронизация доступа к переменным типа bool
От: uzhas Ниоткуда  
Дата: 31.03.14 12:58
Оценка: 10 (1)
Здравствуйте, enji, Вы писали:

E>где-то я читал


ну вот и долгожданная ссылка на msdn : http://msdn.microsoft.com/en-us/library/12a04hfd(VS.80).aspx
и на вики: http://en.wikipedia.org/wiki/Memory_ordering
и на intel :
http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html
http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf

в последнем документе можно искать слово reorder
Re[4]: Синхронизация доступа к переменным типа bool
От: Mr.Delphist  
Дата: 31.03.14 15:22
Оценка:
Здравствуйте, enji, Вы писали:

E>Здравствуйте, Mr.Delphist, Вы писали:


MD>>Ну, с гонкой у атомарных операций всё в порядке, согласен. Но что скажете насчёт реордеринга? Тут атомарность никак не спасёт, если компилятор переставит data flow.


E>Компилятор этого не сделает — volatile. Вот процессор при исполнении инструкций — может. Но где-то я читал, что при работе с volatile msvc вставляет дополнительные инструции для процессора


http://en.wikipedia.org/wiki/Memory_barrier

The keyword volatile does not guarantee a memory barrier to enforce cache-consistency. Therefore the use of "volatile" alone is not sufficient to use a variable for inter-thread communication on all systems and processors


Т.е. опять похоже на частный случай, что подтверждает и MSDN (см. выделенное жирным):

http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208(v=vs.85).aspx

With Visual Studio 2003, volatile to volatile references are ordered; the compiler will not re-order volatile variable access. With Visual Studio 2005, the compiler also uses acquire semantics for read operations on volatile variables and release semantics for write operations on volatile variables (when supported by the CPU).

Re[3]: Синхронизация доступа к переменным типа bool
От: okman Беларусь https://searchinform.ru/
Дата: 31.03.14 16:26
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>А в чём проблема-то нагородить? что заставляет НЕ делать так, как "надо"

MZ>?

Посыл был в том, что решение следует принимать обдуманно, а не только потому, что "так надо".

MZ>Почему все знают, как надо, но как доходит до дела, включают какой-то

MZ>другой ум и "как надо" не делают ?

Я знаю только то, что на IA-32/AMD64 lock здесь не обязателен.
Re[4]: Синхронизация доступа к переменным типа bool
От: okman Беларусь https://searchinform.ru/
Дата: 31.03.14 16:38
Оценка:
Здравствуйте, enji, Вы писали:

E>Но где-то я читал, что при работе с volatile msvc вставляет дополнительные инструции для процессора


Не вставляет.
На IA-32/AMD64 чтение и запись в volatile работает как acquire- и release-барьеры.
То есть, операции "write-1/write-2" всегда будут наблюдаться другими CPU в правильном
порядке, несмотря на store buffers, кэши и т.п. Поэтому за reordering при наличии
volatile можно не бояться. Основной проблемный случай — write/read, вот там нужен явный
хардварный барьер — MemoryBarrier(). Ну а MSVC на компиляторном уровне имеет свои
гарантии и не выполняет реордеринг переменных относительно друг друга, если они
объявлены как volatile, либо используется _ReadWriteBarrier.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.