Мотивация: причина, по которой я рассматриваю это, заключается в том, что мой гениальный руководитель проекта считает, что повышение - это еще одна зависимость, и это ужасно, потому что «вы зависите от этого» (я попытался объяснить качество повышения, а затем через некоторое время сдался :( Меньшая причина, по которой я хотел бы это сделать, заключается в том, что я хотел бы изучить возможности c ++ 11, потому что люди начнут писать код в нем. Итак:
- Есть ли соотношение 1: 1 между
#include<thread> #include<mutex>
эквивалентами и буст-эквивалентами? - Считаете ли вы хорошей идеей заменить буст-контент на c ++ 11
? Я использую примитивно, но есть ли примеры, когда std не предлагает то, что делает boost? Или (богохульство) наоборот?
PS Я использую GCC, поэтому заголовки есть.
Ответы:
Между Boost.Thread и стандартной библиотекой потоков C ++ 11 есть несколько отличий:
std::async
, но Boost нетboost::shared_mutex
блокировка для нескольких читателей / писателей. Аналогичноstd::shared_timed_mutex
доступен только с C ++ 14 ( N3891 ), в то времяstd::shared_mutex
доступен только с C ++ 17 ( N4508 ).boost::unique_future
противstd::future
)std::thread
отличается от использованияboost::thread
--- Boostboost::bind
, которое требует копируемых аргументов.std::thread
позволяет только типы перемещения, такие какstd::unique_ptr
передаваемые в качестве аргументов. Благодаря использованиюboost::bind
семантика заполнителей, таких как_1
вложенные выражения связывания, также может быть различной.join()
илиdetach()
тогдаboost::thread
деструктор и оператор присваивания вызовутdetach()
объект потока, который уничтожается / назначается. Сstd::thread
объектом C ++ 11 это приведет к вызовуstd::terminate()
и отмене приложения.Чтобы прояснить вопрос о параметрах «только для перемещения», ниже приведен действительный код C ++ 11, который передает владение
int
из временногоstd::unique_ptr
параметра параметру,f1
когда запускается новый поток. Однако, если вы используетеboost::thread
его, он не будет работать, так как он используетсяboost::bind
внутри, иstd::unique_ptr
не может быть скопирован. Существует также ошибка в библиотеке потоков C ++ 11, предоставляемой с GCC, которая препятствует этой работе, поскольку она также используетсяstd::bind
в реализации.Если вы используете Boost, то вы, вероятно, можете безболезненно переключаться на потоки C ++ 11, если ваш компилятор поддерживает его (например, в последних версиях GCC в linux в основном реализована полная библиотека потоков C ++ 11, доступная в
-std=c++0x
режиме).Если ваш компилятор не поддерживает потоки C ++ 11, вы можете получить стороннюю реализацию, такую как Just :: Thread , но это все еще является зависимостью.
источник
lock
/unlock
для писателей против 'lock_shared / unlock_shared' для читателей). Несколько читателей могут вызывать lock_shared без блокировки, если только писатели его не используют.shared_mutex
документах находятся на boost.org/doc/libs/1_47_0/doc/html/thread/... . Вы можете заблокировать мьютекс как общий или исключительный, а затем использовать соответствующую функцию разблокировки. Вы также можете использовать типы RAII для этого (shared_lock
берет общую блокировку чтения иlock_guard
иunique_lock
эксклюзивную блокировку). Я попытался прояснить вопрос о типах только для перемещения.try_scoped_lock
функциональность покрытаstd::unique_lock
. Существует конструктор, который принимает мьютекс иstd::try_to_lock
, а затем будет вызыватьtry_lock()
мьютекс, а неlock()
. См. Stdthread.co.uk/doc/headers/mutex/unique_lock/…std::thread
в значительной степени смоделирован послеboost::thread
, с некоторыми отличиями :Это с 2007 года, поэтому некоторые пункты больше не действительны: теперь
boost::thread
имеетnative_handle
функцию, и, как отмечают комментаторы,std::thread
больше не имеет отмены.Я не смог найти каких-либо существенных различий между
boost::mutex
иstd::mutex
.источник
std::thread
не имеет отмены; этоboost::thread
то, что делает!interrupt()
boost :: thread? Также кажется, что это оригинальное предложение, которое изменилось с 2007 года.Есть одна причина не переходить на
std::thread
.Если вы используете статическое связывание,
std::thread
становится непригодным из-за следующих ошибок / функций gcc:А именно, если вы позвоните
std::thread::detach
илиstd::thread::join
это приведет к исключению или сбою, тоboost::thread
в этих случаях работает нормально.источник
libpthread.a
. Вы абсолютно уверены в том, что говорите?Wl,--whole-archive -lpthread -Wl,--no-whole-archive
, см. этот ответ, например, stackoverflow.com/a/23504509/72178 . Но это не очень простой способ связи,libpthread.a
а также считается плохой идеей.Корпоративный случай
Если вы пишете программное обеспечение для предприятия, которое должно работать на умеренных или больших операционных системах и, следовательно, собирать с различными компиляторами и версиями компиляторов (особенно относительно старых) для этих операционных систем, я советую вам избегать C ++ 11 в целом на данный момент. Это означает, что вы не можете использовать
std::thread
, и я бы порекомендовал использоватьboost::thread
.Базовый / Tech Startup Case
Если вы пишете для одной или двух операционных систем, вы точно знаете, что вам когда-либо понадобится создавать только с помощью современного компилятора, который в основном поддерживает C ++ 11 (например, VS2015, GCC 5.3, Xcode 7), и вы этого еще не сделали в зависимости от библиотеки наддува, то
std::thread
может быть хорошим вариантом.Мой опыт
Я лично неравнодушен к закаленным, интенсивно используемым, высоко совместимым, высокосогласованным библиотекам, таким как boost по сравнению с очень современной альтернативой. Это особенно верно для сложных предметов программирования, таких как многопоточность. Кроме того, я уже давно добился большого успеха
boost::thread
(и в целом в Boost) в широком спектре сред, компиляторов, потоковых моделей и т. Д. Когда это мой выбор, я выбираю boost.источник
В Visual Studio 2013
std::mutex
кажется, что он ведет себя не такboost::mutex
, как у меня, что вызвало некоторые проблемы (см. Этот вопрос ).источник
Что касается std :: shared_mutex, добавленного в C ++ 17
Другие ответы здесь дают очень хороший обзор различий в целом. Тем не менее, есть несколько проблем,
std::shared_mutex
которые буст решает.Восстанавливаемые мутанты. Они отсутствуют в
std::thread
. Они позволяют преобразовать читателя в писателя, не позволяя другим писателям входить до вас . Они позволяют выполнять такие вещи, как предварительная обработка больших вычислений (например, переиндексация структуры данных) в режиме чтения, а затем обновляться до записи, чтобы применить переиндекс, удерживая блокировку записи только в течение короткого времени.Честность. Если вы постоянно читаете с
std::shared_mutex
, ваши писатели будут заблокированы на неопределенный срок. Это потому, что если придет другой читатель, им всегда будет отдан приоритет. При этомboost:shared_mutex
все потоки в конечном итоге получат приоритет. (1) Ни читатели, ни писатели не будут голодать.Дело в том, что если у вас система с очень высокой пропускной способностью, без простоев и с высокой конкуренцией,
std::shared_mutex
вы никогда не будете работать без ручной сборки приоритетной системы поверх нее.boost::shared_mutex
будет работать из коробки, хотя в некоторых случаях вам, возможно, придется повозиться с ним. Я бы сказал, чтоstd::shared_mutex
поведение - это скрытая ошибка, ожидающая появления в большинстве кодов, которые ее используют.(1) Фактический алгоритм использует на основе ОС планировщик потоков. По моему опыту, когда чтение насыщено, в Windows более длинные паузы (при получении блокировки записи), чем в OSX / Linux.
источник
Я попытался использовать shared_ptr из std вместо boost и на самом деле обнаружил ошибку в реализации gcc этого класса. Мое приложение зависало из-за того, что деструктор вызывался дважды (этот класс должен быть потокобезопасным и не должен вызывать таких проблем). После перехода на boost :: shared_ptr все проблемы исчезли. Текущие реализации C ++ 11 все еще не являются зрелыми.
Boost также имеет больше возможностей. Например, заголовок в версии std не предоставляет сериализатор потоку (т.е. cout << duration). Boost имеет много библиотек, которые используют свои собственные и т. Д. Эквиваленты, но не взаимодействуют с версиями std.
Подводя итог: если у вас уже есть приложение, написанное с использованием boost, безопаснее сохранить свой код таким, каким он есть, вместо того, чтобы приложить некоторые усилия для перехода на стандарт C ++ 11.
источник
shared_ptr
Деструктор не должны быть поточно-, это неопределенное поведение , чтобы иметь одну нить с доступом объект , а другой поток разрушает его. Если вы думаете, что нашли ошибку в shared_ptr GCC, пожалуйста, сообщите об этом , в противном случае на балансе вероятности вы используете ее неправильно.