Многопоточность в C++, с чего начать?

Я хотел бы начать изучать многопоточность в C++. Я изучаю это и на Java. В Java, если я напишу программу, использующую многопоточность, она будет работать где угодно. Однако в С++ многопоточность не зависит от API для конкретной платформы? Если это так, то это может помешать переносимости.

Как я могу сделать многопоточность в C++, не вызывая проблем с переносимостью? Является ли библиотека Boost thread хорошим решением?

В качестве примечания - как вообще возможно реализовать многопоточность в виде библиотеки? Разве это не то, что должен делать компилятор?


person Cam    schedule 26.06.2010    source источник
comment
В качестве предостережения вам придется больше думать о безопасности потоков в C++. Нельзя просто добавить ключевые слова синхронизации для методов класса, чтобы сделать их потокобезопасными. Как правило, вам понадобятся такие инструменты, как мьютексы или другие формы критических секций, атомарные операции и т. д. Однако вы сможете написать очень эффективный многопоточный код, если сделаете это правильно. Вы даже можете написать свои собственные распределители памяти с пулами памяти для каждого потока, но это гораздо более низкоуровневый и гораздо сложнее написать для корректности, чем Java.   -  person stinky472    schedule 27.06.2010
comment
(+1) @ stinky472: Именно поэтому я хочу изучить многопоточность как в C++, так и в Java. Я чувствую, что Java, как правило, хороша для высокоуровневых вступлений ко многим темам, но простое использование Java может слишком сильно смущать программиста и не знакомить его с некоторыми очень важными концепциями. Поэтому, пока я изучаю многопоточность на Java, я хочу одновременно изучить его на C++, чтобы убедиться, что я изучил все, что должен.   -  person Cam    schedule 27.06.2010


Ответы (9)


Если у вас нет компилятора, поддерживающего C++0x еще (доступно, например, в Visual Studio C++ 2010), используйте потоки ускорения. (Если вы не используете фреймворк, который уже поддерживает многопоточность, что не так - иначе вы бы не задавали вопрос -). Эти потоки ускорения стали фактически стандартом в новом C++. До этого C++ сам не знал ни о каком потоке.

Стандартные блоки многопоточности TBB также могут быть вам интересны, если вы хотите изучить другие аспекты параллельного программирования.

Что касается Qt: если вам нужна только поддержка потоков, это совершенно излишне. У него ужасно медленное время прохождения от компиляции до результата. Это действительно хорошо продуманная мысль. Но не официальный стандарт, как потоки C++0x от boost. Поэтому я бы не взял его в качестве первого выбора.

person jdehaan    schedule 26.06.2010
comment
Спасибо. Все ответы были очень полезными, но этот был самым информативным. - person Cam; 27.06.2010

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

Библиотека потоков Boost — очень хорошее решение.

Я также рекомендую проверить ACE.

person Alan    schedule 26.06.2010

Начнем в обратном порядке:

Как можно реализовать многопоточность в библиотеке?

Это не так, по крайней мере, не в (чистом) С++. Для этого требуется поддержка языка (компилятор — это только реализация).

На данный момент используются 2 вещи:

  • ассемблерный код для некоторых деталей (как в библиотеке pthread)
  • специальные инструкции компилятора для других (в зависимости от компилятора и платформы)

Оба хрупкие и требуют огромного количества работы для переносимости. По сути, это означает множество #ifdef частей кода для проверки компилятора и целевой архитектуры, проверки поддержки некоторых директив и т. д.

Вот почему было сочтено необходимым добавить поддержку многопоточности в C++0x.

Как сделать многопоточность?

Еще до того, как вы выберете библиотеку, вы должны выбрать метод. Существует 2 способа программирования многопоточных приложений (и их можно комбинировать):

  • Общайтесь путем обмена: это означает использование мьютексов, атомарных операций и т. д. Вы можете использовать pthread на платформах Linux, но я бы рекомендовал Boost.Thread (среди прочего) из-за его переносимости.
  • Обменивайтесь, общаясь: более поздний вариант, адаптированный для распределенных вычислений, связанный с функциональными языками. Это означает передачу сообщений из одного потока в другой без совместного использования каких-либо ресурсов. Вы можете использовать FastFlow или Intel Основные блоки потока, также известные как TBB.

Вы можете объединить их, но лучше этого не делать. Лично я нашел описание FastFlow совершенно потрясающим: оно поощряет программирование без блокировок. Кроме того, основное преимущество второго метода заключается в том, что он лучше приспособлен к многопроцессорному программированию и масштабируется для распределенных сред.

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

person Matthieu M.    schedule 26.06.2010
comment
Не компилятор должен поддерживать потоки, а ОС. Например, в чистом C++ это можно сделать, включив заголовки pthreads, используя его функции и связавшись с его библиотекой. Компилятор ничего не знает о самих pthreads. - person Gianni; 26.06.2010
comment
Ну, я бы сказал, что использование библиотеки на основе ассемблера - это не использование чистого C++ ;) Но я поправлю компилятор, я имел в виду язык. - person Matthieu M.; 26.06.2010
comment
@Matthieu, я имел в виду, что приложение на самом деле просто запрашивает у ОС поток, и ОС должна создать и инициировать поток. ASM или встроенные функции компилятора (которые просто означают больше ASM) используются только для атомарных вычислений. Мьютексы, семафоры, сами потоки — все зависит от ОС. - person Gianni; 26.06.2010
comment
А чем ваш второй метод более поздний? IPC в основном это. Обратите внимание, что вы можете делать это между процессами, а не только между потоками. - person ninjalj; 27.06.2010
comment
@Джанни, компилятор по-прежнему должен знать о существовании возможности нескольких потоков, чтобы не применять оптимизации или переупорядочения, которые были бы безопасны для одного потока, но небезопасны для нескольких потоков. - person Logan Capaldo; 27.06.2010
comment
@Logan Я могу ошибаться, но я думаю, что компилятор (на самом деле gcc) этого не знает, поэтому у него есть барьеры атомарности и памяти, которые программист должен поставить сам. - person Gianni; 27.06.2010
comment
@ Джанни Действительно. Стандарты ничего не говорят о модели памяти (это может измениться в C++0x). См. gcc.gnu.org/ml/gcc/2007-10/msg00266. .html и gcc.gnu.org/ml/gcc /2007-10/msg00275.html - person ninjalj; 27.06.2010
comment
@Gianni atomics и барьеры памяти - это именно то, с чем вы расширяете язык, чтобы предоставить компилятору эту информацию. Компилятор действительно (частично) должен поддерживать потоки. - person Logan Capaldo; 27.06.2010
comment
@Logan Да, ты прав, я думаю, это зависит от точки зрения. Для меня это просто синхронизация, которая используется для IPC, HW-доступа и потоков. В то время как запуск нового «pid» зависит от ОС. - person Gianni; 28.06.2010

также проверьте Qt

person technomage    schedule 26.06.2010

Чтобы предложить предложение, отличное от Boost, я использую Pthreads (или Pthreads-Win32 в Windows). Это очень простая библиотека, которую можно сделать своими руками, но она предоставляет вам все, что вам нужно, и ничего больше. Он очень легкий по сравнению с Boost, и вы можете легко найти обертки C++ вокруг него, чтобы получить абстракции более высокого уровня.

person Victor Liu    schedule 26.06.2010
comment
Библиотека потоков от boost — это библиотека только для заголовков шаблонов. Это не создает больших накладных расходов. Хорошо, куча необходимых файлов может быть огромной, но в конечном результате у вас будет всего несколько байтов от экземпляра шаблона. - person jdehaan; 26.06.2010
comment
@jdehaan: Можете ли вы уточнить, что вы подразумеваете под библиотекой только заголовков шаблонов? - person Cam; 26.06.2010
comment
Должен признаться, я тоже очень удивлен только заголовком. Это: libboost_thread-vc100-mt-gd-1_43.lib не похоже на заголовок. - person Matthieu M.; 26.06.2010
comment
О, я думаю, что я, вероятно, напортачил с материалами shared_ptr, unique_ptr, weak_ptr, которые содержат только заголовки (@incrediman: не нужны библиотеки или dll, только *.hpp файлов). Извините, вы правы, тогда это не так уж и мало... DLL поставляется с классами потоков и мьютексов и многим другим. - person jdehaan; 27.06.2010
comment
Вот хорошая ветка, в которой обсуждаются плюсы и минусы от экспертов в отношении только заголовков или нет для частей потоков повышения: old.nabble.com/ - person jdehaan; 27.06.2010

вы также можете использовать openmp http://openmp.org. Его поддерживают многие компиляторы, в том числе MS, GCC/G++ и Intel. Хотя вы не получаете явного контроля над потоками, его более высокий уровень абстракции параллелизма иногда более эффективен (как во время кодирования, так и во время выполнения), и код намного легче понять. Это не сильно поможет вам, если вы работаете с графическим интерфейсом, но для масштабируемых вычислений стоит взглянуть.

person phlip    schedule 26.06.2010

Библиотека Boost Threading, вероятно, лучшее место для начала изучения C++. Предоставляет вам конструкции потоков, а также все мьютексы и объекты управления, необходимые для написания реального работающего многопоточного приложения.

person Conradaroma    schedule 26.06.2010

В С++ 11 «Библиотека поддержки потоков» представлена ​​под заголовком <thread>.

Более подробную информацию можно найти по ссылкам ниже

https://en.cppreference.com/w/cpp/thread

http://www.cplusplus.com/reference/thread/

person pasha    schedule 06.09.2018

Если вы делаете это из интереса, чтобы улучшить свои знания о различных моделях программирования и языковых навыках, то библиотека Boost будет отличным способом. Однако я бы долго и усердно думал о создании каких-либо производственных приложений с использованием многопоточного C++.

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

Императивные языки, такие как C++, Java или C# (с их изменяемыми переменными, разделяемой памятью и примитивами блокировки/сигнализации) очень часто являются наименее доступным способом создания многопоточных приложений. Обычно существуют очень хорошие однопоточные варианты реализации для решения большинства проблем приложений в пользовательском пространстве (в отличие от ядра или встроенных), в том числе на многоядерных машинах.

Если вы действительно хотите создавать надежные «многопоточные» приложения, я бы посоветовал вам проверить функциональные языки, такие как Erlang, Haskell, F # или Clojure.

person bjg    schedule 26.06.2010