Отсоединенные и присоединяемые потоки POSIX

Я использую библиотеку pthread для создания и объединения потоков в C.

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

  2. Законно ли не выполнять pthread_join() в присоединяемом (по умолчанию) потоке? Или такой поток всегда должен использовать функцию detach() перед pthread_exit()ing?


person Community    schedule 21.09.2010    source источник


Ответы (2)


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

  2. «Легально» не присоединяться к присоединяемому потоку; но обычно это не рекомендуется, потому что (как отмечалось ранее) ресурсы не будут освобождены до тех пор, пока поток не будет присоединен, поэтому они останутся связанными на неопределенный срок (до выхода программы), если вы не присоединитесь к нему.

person Jonathan Leffler    schedule 21.09.2010
comment
сомнение: в случае отсоединенных потоков, что, если основной поток завершит выполнение до завершения отсоединенного потока? Я думаю, что это завершит процесс, убивающий все потоки. Итак, в каких сценариях используются отсоединенные потоки, потому что я должен быть уверен, что отсоединенный поток завершил выполнение? - person Ajax; 18.11.2014
comment
@Ajax: эмпирически, если основной поток завершается, программа завершается, а потоки… завершаются. По крайней мере, так выглядит поведение в Mac OS X (10.10.1 Yosemite). Я не могу найти в документации POSIX ничего, что указывало бы на то, что другие потоки продолжаются, если вызывается exit(), _exit() или _Exit(). Если основной поток выполняет pthread_exit(), то другие потоки получают возможность завершиться. - person Jonathan Leffler; 18.11.2014
comment
В другом примечании: отделяемые потоки хороши, когда у вас уже есть какой-то другой механизм опроса; вы можете использовать тот же механизм опроса, чтобы проверить состояние результата и, таким образом, узнать, завершен ли поток. Это случай, он готов? Если это так, используйте его. - person Engineer; 19.02.2015
comment
Могу ли я вызвать pthread_detach перед его выходом, чтобы избежать утечек памяти, если я забуду вызвать pthread_join? - person Antonio Petricca; 31.03.2016
comment
@DareDevil: Да, но…. Вы должны отсоединять поток, потому что вам не нужно знать статус возврата потока и вам не нужно знать, что он завершен, а не потому, что вы можете забыть присоединиться к нему. И как только вы отсоединились, вы не должны пытаться присоединиться к потоку. - person Jonathan Leffler; 31.03.2016

Когда я должен создать поток как отдельный, с самого начала?

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

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

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

Псевдокод может выглядеть так:

/* A server application */

void process(void *arg)
{
    /* Detach self. */
    pthread_detach(pthread_self());
    
    /* process a client request. */
    
    pthread_exit(NULL);
}

int main(void)
{

    while (not_done) {
        pthread_t t_id;
        errno = pthread_create(&t_id, NULL, process, NULL);
        if (errno) perror("pthread_create:");
    }

    /* There may be pending requests at this point. */
    
    /* Just exit the main thread - not the whole program - so that remaining
       requests that may still be processed can continue. */
    pthread_exit(NULL);
}

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

Предлагает ли он какое-либо преимущество в производительности по сравнению с присоединяемым потоком?

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

Законно ли не выполнять pthread_join() в присоединяемом (по умолчанию) потоке?

Да, можно не присоединяться к треду. pthread_join - это просто удобная функция, которую ни в коем случае нельзя использовать, если вам это не нужно. Но обратите внимание, что созданные потоки являются присоединяемыми потоками по умолчанию.

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

Или такой поток всегда должен использовать функцию detach() перед вызовом pthread_exit()?

Не обязательно. Но вы часто хотите решить, хотите ли вы присоединяемый или отдельный поток во время создания.


Обратите внимание, что хотя отсоединяемый поток можно создать, установив атрибут PTHREAD_CREATE_DETACHED с вызовом pthread_attr_setdetachstate, поток может принять решение об отсоединении в любой момент времени, например с pthread_detach(pthread_self()). Кроме того, поток, имеющий идентификатор потока (pthread_t) другого потока, может отсоединиться с помощью pthread_detach(thread_id);.

person P.P    schedule 18.07.2020
comment
В чем разница между выходом из основного потока и выходом из всей программы/приложения? - person Yd Ahhrk; 10.06.2021
comment
@YdAhhrk Вызов pthread_exit из основного потока завершает работу только этого потока, и процесс будет продолжать работать, если есть другие запущенные потоки. Вот что я имею в виду под выходом из основного потока. OTOH, например, вызов exit из любого потока приводит к выходу из всего процесса/приложения. - person P.P; 12.06.2021