В C/C++ энергозависимые переменные, как гарантируют, будут иметь в конечном счете последовательную семантику между потоками?

Есть ли гарантия по какому-либо обычно сопровождаемому стандарту (ISO C или C++ или какая-либо из спецификаций POSIX/SUS), что переменная (возможно, отметил энергозависимый), не охраняемый взаимным исключением, к которому получают доступ несколько потоков, станет в конечном счете последовательной, если это будет присвоено?

Для обеспечения определенного примера рассмотрите два потока, совместно использующие переменную v с нулем начального значения.

Поток 1: v = 1

Поток 2: в то время как (v == 0) урожай ();

Поток 2, гарантировал, что завершился в конечном счете? Или это может очевидно вращаться навсегда, потому что когерентность кэш-памяти никогда не вталкивает и делает присвоение видимым в потоке 2 кэш?

Я знаю, C и стандарты C++ (перед C++ 0x) не говорят вообще о потоках или параллелизме. Но мне любопытно, если C++ 0x модель памяти, или pthreads, или что-либо еще, гарантирует это. (По-видимому, это действительно на самом деле работает над Windows на 32-разрядном x86; я задаюсь вопросом, является ли это что-то, на что можно обычно полагаться или если это просто, оказывается, работает там).

10
задан Jack Lloyd 24 June 2010 в 21:46
поделиться

5 ответов

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

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

РЕДАКТИРОВАТЬ: всем, кто все еще не уверен в ключевом слове volatile - volatile гарантирует, что компилятор не будет генерировать код, который явно кэширует данные в регистрах, но это НЕ то же самое, что иметь дело с оборудованием, которое прозрачно кэширует / меняет порядок чтения и записи. Прочтите, например, this или this , или эта статья доктора Доббса, или ответ на этот SO вопрос, или просто выберите свой любимый компилятор, нацеленный на слабо согласованная архитектура памяти, такая как Cell, напишите тестовый код и сравните то, что генерирует компилятор, с тем, что вам нужно, чтобы гарантировать, что записи будут видны другим процессам.

12
ответ дан 3 December 2019 в 16:28
поделиться

Если я правильно понял соответствующие разделы, C ++ 0X не гарантирует этого для автономной переменной или даже для изменчивой переменной (volatile не предназначен для этого использования), но представит атомарные типы, на которые у вас будет гарантия (см. заголовок ).

5
ответ дан 3 December 2019 в 16:28
поделиться

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

Но, честно говоря, это очень плохой стиль - делать опрос с ожиданием события. Даже если вы делаете yield, ваш процесс будет переноситься снова и снова, ничего не делая.

Поскольку вы уже знаете, как поместить переменную в такое место, где она будет доступна обоим, почему бы не использовать правильные инструменты для выполнения ожидания, которое не съедает ресурсы? Пара pthread_mutex_t и pthread_cond_t должна отлично справиться с этой задачей.

0
ответ дан 3 December 2019 в 16:28
поделиться

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

Поскольку вы явно говорите «без мьютексов», pthreads не применяется.

Кроме того, поскольку C ++ не имеет модели памяти, это зависит от архитектуры оборудования.

3
ответ дан 3 December 2019 в 16:28
поделиться

Гарантировано ли, что поток 2 в конце концов завершится? Или он может вращаться вечно, потому что когерентность кэша никогда не сработает и не сделает присвоение видимым в кэше потока 2?

Если переменная не является переменной, у вас нет никаких гарантий. До С++0x стандарт просто ничего не говорил о потоках, а поскольку переменная не является волатильной, чтение/запись не считаются наблюдаемыми побочными эффектами, поэтому компилятору разрешено жульничать. После С++0x это состояние гонки, которое явно указано как неопределенное поведение.

Если переменная является волатильной, вы получаете гарантию, что чтение/запись произойдет, и что компилятор не будет перестраиваться по отношению к другим доступам к волатильной памяти. (Однако это само по себе не гарантирует, что CPU не будет переупорядочивать эти обращения к памяти - только то, что компилятор не будет этого делать)

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

Так что нет, в общем случае не гарантируется, что это будет работать правильно, даже с volatile. Это может быть, и, вероятно, часто будет, но не всегда (и это зависит от того, что происходит после цикла). Это зависит от того, насколько далеко компилятор готов зайти в оптимизации. Но разрешено зайти достаточно далеко, чтобы сломать код. Так что не полагайтесь на это. Если вы хотите синхронизировать что-то вроде этого, используйте барьеры памяти. Они для этого и предназначены. (И если вы это сделаете, вам даже не понадобится volatile)

2
ответ дан 3 December 2019 в 16:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: