Linux C ++: вызывает ли возврат из main () завершение многопоточного приложения? - PullRequest
9 голосов
/ 22 июля 2010

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

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

В C ++, похоже, это не так - как только основной поток возвращает процесс завершается, а другие потоки все еще работают. Для моего текущего приложения это легко решается с помощью приложения pthread_join(), но мне интересно, что вызывает такое поведение. Этот компилятор (gcc) специфичен, специфичен для pthreads, или тип поведения распространяется на большинство / все платформы, для которых был реализован C ++? Настраивается ли это поведение в pthreads (я просматривал API pthread в функциях pthread_attr_*() и не видел ничего, что выглядело соответствующим).

Совершенно отдельный вопрос, но пока вы здесь ... для чего нужно использовать pthread_detatch()?

Ответы [ 3 ]

12 голосов
/ 22 июля 2010

Да.В современном linux (что более важно в более новых версиях GNU libc) exit_group - это системный вызов, используемый при возврате main, а не в виде exit.exit_group описывается следующим образом:

Этот системный вызов эквивалентен exit (2) за исключением того, что он завершает не только вызывающий поток, но и все потоки в группе потоков вызывающего процесса.

Стоит отметить, что в текущем стандарте c ++ не упоминается о потоках , поэтому это поведение не специфично для c ++, а специфично для вашей конкретной реализации.Тем не менее, каждая реализация, которую я лично видел, убивает все потоки, когда основной поток завершается.

РЕДАКТИРОВАТЬ: Стоит также отметить ответ Джонатана Леффлера, который указывает, что стандарт POSIX действительно делаетзадайте это поведение, так что это, конечно, нормально для приложения, использующего pthreads для своей многопоточности.

РЕДАКТИРОВАТЬ: Чтобы ответить на продолжение о pthread_detach.По сути, это считается утечкой ресурсов, если вы не присоединяетесь к неотсоединенному потоку.Если у вас есть долгосрочное задание, которое вам не нужно «ждать», и оно просто «заканчивается, когда заканчивается», вы должны отсоединить его, что не приведет к утечке ресурсов, когда оно завершится без соединения.Страница man говорит следующее:

Функция pthread_detach () помечает поток, идентифицированный потоком, как отсоединенный.Когда отключенный поток завершается, его ресурсы автоматически возвращаются обратно в систему без необходимости присоединения другого потока к завершенному потоку.

Итак, быстрый и грязный ответ: «когда вы не делаете»не волнуйтесь, когда он заканчивается, отсоедините его. Если другой поток заботится о том, когда он заканчивается и должен ждать его завершения, то не надо. "

11 голосов
/ 22 июля 2010

Да

Стандарт POSIX гласит:

§3.297 Завершение процесса

Существует два вида завершения процесса:

  1. Нормальное завершение происходит при возврате из main () по запросу с функциями exit (), _exit () или _Exit (); или когда последний поток в процессе завершается, возвращаясь из своей функции запуска, вызывая функцию pthread_exit (), или через отмену.

  2. Аварийное завершение происходит по запросу функции abort () или при получении некоторых сигналов.

Применяется первое нормальное условие завершения. (Обратите внимание, что стандарт C ++ (1998, 2003) ничего не говорит о потоках.)


Относительно pthread_detach ()

Стандарт POSIX (снова) гласит:

Функция pthread_detach () должна указывать реализации, что память для потока потока может быть восстановлена, когда этот поток завершается. Если поток не завершен, pthread_detach () не должен вызывать его прекращение.

И обоснование гласит:

Функции pthread_join () или pthread_detach () должны в конечном итоге вызываться для каждого создаваемого потока, чтобы можно было восстановить хранилище, связанное с этим потоком.

Было высказано предположение, что функция "отсоединения" не нужна; атрибут создания потока detachstate является достаточным, поскольку поток никогда не должен динамически отсоединяться. Однако необходимость возникает как минимум в двух случаях:

  1. В обработчике отмены для pthread_join () почти необходимо иметь функцию pthread_detach () для отсоединения потока, в котором ожидал pthread_join (). Без этого было бы необходимо, чтобы обработчик сделал еще одну функцию pthread_join (), чтобы попытаться отсоединить поток, что задержало бы обработку отмены на неограниченный период и ввело бы новый вызов функции pthread_join (), которая сама может нуждаться в отмене обработчик. В этом случае почти необходим динамический отрыв.

  2. Для отсоединения «начального потока» (что может быть желательно в процессах, которые настраивают потоки сервера).

0 голосов
/ 22 июля 2010

Это не зависит от компилятора и является стандартным поведением;приложение завершается при выходе из main (), поэтому, если вы хотите предотвратить завершение приложения, вам нужно, чтобы main () блокировал его до тех пор, пока не завершатся все потоки, что вы делаете, присоединяясь к этим потокам.Когда вы вызываете pthread_create, он выделяет ресурсы для этого потока.Ресурсы не освобождаются, пока вы не выполните pthread_join (который блокирует, пока поток не завершится) или pthread_detach (который заставляет поток автоматически освобождать ресурсы при выходе из этого потока).Вы должны использовать pthread_detach всякий раз, когда вы запускаете фоновый поток, который завершается, когда его задача завершена и которого вам не нужно ждать.

Чтобы сделать это немного более конкретным, предположим, что у вас есть несколько потоков, которые выполняютчасть вычисления, а затем вы каким-то образом агрегируете результат.Это может быть случай, когда вы будете использовать соединение, потому что вам нужны результаты потоков для продолжения.Теперь рассмотрим случай, когда поток прослушивает сокет и обрабатывает входящие запросы, пока флаг не укажет, что поток должен выйти.В этом случае вы должны использовать pthread_detach, так как ничто не требует завершения потока для продолжения, и поэтому ресурсы, связанные с этим потоком, должны уходить автоматически.

...