Что именно делает threading = multi при компиляции boost?

Я не совсем уверен, что именно threading=multi флаг делает при наращивании буста. В документации сказано:

 Causes the produced binaries to be thread-safe. This requires proper
support in the source code itself.

который не кажется очень конкретным. Означает ли это, что доступ к, например, буст-контейнерам охраняется mutexes/locks или похожие? Поскольку производительность моего кода очень важна, я бы хотел свести к минимуму ненужные мьютексы и т. Д.

Еще несколько деталей:

Мой код представляет собой подключаемый модуль DLL, который загружается в многопоточное стороннее приложение. Я статически связываю повышение с DLL (у подключаемого модуля не должно быть никаких других зависимостей, кроме стандартных Windows DLL, поэтому я вынужден это сделать).

Хотя приложение является многопоточным, большинство функций в моей DLL всегда вызывается только из одного потока, и поэтому доступ к контейнерам не нужно защищать. Я явно охраняю оставшиеся места моего кода, которые можно вызывать из нескольких потоков, используя boost::mutex и друзья.

Я пробовал наращивать буст с обоими threading=multi а также threading=single и оба, кажется, работают, но мне бы очень хотелось знать, что я здесь делаю.

11

Решение

Нет, threading=multi не означает, что такие вещи, как буст-контейнеры, внезапно станут безопасными для одновременного доступа несколькими потоками (это будет непомерно дорого с точки зрения производительности).

Скорее, что это значит теоретически это повышение будет скомпилировано, чтобы быть в курсе. По сути, это означает, что методы и классы boost будут вести себя разумно по умолчанию при доступе из нескольких потоков, так же, как классы в библиотеке std. Это означает, что вы не можете получить доступ к тот же объект из нескольких потоков, если не указано иное, но вы можете безопасно обращаться к различным объектам из нескольких потоков. Это может показаться очевидным, даже без явной поддержки, но любой static используемое библиотекой состояние нарушит эту гарантию, если не будет защищено. С помощью threading=multi гарантирует, что любое такое общее состояние является свойством, охраняемым мьютексом или каким-либо другим механизмом.

В прошлом аналогичные аргументы или разновидности stdlib были доступны для библиотек st и C ++, поставляемых моими компиляторами, хотя сегодня доступны в основном только многопоточные версии.

Вероятно, есть небольшие недостатки при компиляции с threading=multi, учитывая, что только ограниченное количество статического состояния должно быть синхронизировано. Ваш комментарий, что ваша библиотека будет в основном вызов только одной нитью не внушает большого доверия — в конце концов, это те скрытые ошибки, которые заставят вас проснуться в 3 часа ночи от вашего босса после ночи долгого пьянства.

Пример буста shared_ptr информативно. С threading=single, даже не гарантируется, что независимое манипулирование двумя shared_ptr экземпляры из нескольких потоков безопасны. Если они указывают на один и тот же объект (или, теоретически, в некоторых экзотических реализациях, даже если они этого не делают), вы будете генерировать неопределенное поведение, потому что совместно используемое состояние не будет манипулироваться соответствующими средствами защиты.

С threading=multiэтого не произойдет. Тем не менее, это все еще не безопасно чтобы получить доступ к тому же shared_ptr экземпляр из нескольких потоков. То есть он не дает никаких гарантий безопасности потоков, которые не задокументированы для рассматриваемого объекта, — но он дает гарантии «ожидаемого / разумного / по умолчанию» независимости независимых объектов. Не существует хорошего названия для этого уровня безопасности потоков по умолчанию, но на самом деле это то, что сегодня обычно предлагают все стандартные библиотеки для многопоточных языков.

В завершение стоит отметить, что Boost.Thread неявно всегда компилируется с threading=multi — поскольку использование многопоточных классов boost является неявным намеком на наличие нескольких потоков. С помощью Boost.Thread без многопоточной поддержки было бы бессмысленно.

Теперь, после всего вышесказанного, приведенная выше теоретическая идея лежит в основе компиляции boost «с поддержкой потоков» или «без поддержки потоков», которая является целью threading= флаг. На практике, с тех пор как этот флаг был введен, многопоточность стала по умолчанию, а однопоточность — исключением. Действительно, многие компиляторы и компоновщики, которые по умолчанию настроены на однопотоковое поведение, теперь по умолчанию используют многопоточность — или, по крайней мере, требуют только одного «подсказки» (например, наличие -pthread в командной строке) для перехода к многопоточности.

Кроме того, были также предприняты согласованные усилия, чтобы сделать ускоренную сборку «умной» — в том случае, если среда благоприятствует переходу в многопоточный режим. Это довольно расплывчато, но обязательно так. Это становится таким же сложным, как слабое связывание символов pthreads, так что решение об использовании кода MT или ST фактически откладывается до времени выполнения — если pthreads доступен во время выполнения, будут использоваться эти символы, в противном случае слабо связанные заглушки — которые ничего не делают на всех — будет использоваться.

Суть в том, что threading=multi является правильным и безвредным для вашего сценария, особенно если вы создаете двоичный файл, который вы распространяете на другие хосты. Если ты не особенный, это очень вероятно что он будет работать в любом случае из-за эвристики времени сборки и даже времени выполнения, но у вас есть шанс молча использовать пустые методы-заглушки или иным образом использовать MT-небезопасный код. Есть несколько минусов в использовании правильного варианта — но некоторые подробности также можно найти в комментариях к этому пункту и ответе Игоря.

16

Другие решения

После некоторого копания выясняется, что threading=single не имеет большого эффекта, как и следовало ожидать. В частности, это не влияет BOOST_HAS_THREADS макрос и, следовательно, не настраивает библиотеки для использования в однопоточной среде.

С gcc threading=multi просто подразумевает #define BOOST_HAS_PTHREADS, в то время как с MSVC это не производит никакого видимого эффекта. Paricularly, _MT определяется как в threading=single а также threading=multi режимы.

Однако обратите внимание, что можно явно настроить библиотеки Boost для однопоточного режима, определив соответствующий макрос, например BOOST_SP_DISABLE_THREADS , BOOST_ASIO_DISABLE_THREADS, или глобально с BOOST_DISABLE_THREADS,

5

Давайте будем краткими. Causes the produced binaries to be thread-safe означает, что Boost-код адаптирован к этому разные потоки могут использовать разные объекты Boost. В частности, это означает, что код Boost будет уделять особое внимание безопасности потоков при доступе к скрытым глобальным или статическим объектам, которые могут использоваться при реализации библиотек Boost. Он не позволяет различным потокам одновременно использовать одни и те же объекты Boost. без защиты (замки / мьютексы / …).

Редактировать: Некоторые библиотеки Boost могут документировать дополнительную безопасность потоков для определенных функций или классов. Например asio::io_service по предложению Игоря Р. в комментарии.

2

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

Я думаю, что включение этой опции — путь.

Для дальнейшего использования: BOOST библиотеки в режиме многопоточности

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector