Как реализован pthread_join? - PullRequest
10 голосов
/ 12 мая 2010

Я немного новичок в потоке, поэтому вам придется простить наивность этого вопроса.

Как реализуется pthread_join и как это влияет на планирование потоков?

Я всегда представлял pthread_join, реализованный с помощью цикла while, просто вызывая выход вызывающего потока до завершения целевого потока. Вот так (очень приблизительный псевдокод):


atomic bool done;

thread_run {

    do_stuff();
    done = true;

}

thread_join {

    while(!done) {
        thread_yield();
    //  basically, make the thread that calls "join" on
    //  our thread yield until our thread completes
    }
}

Это точное описание, или я сильно упрощаю процесс?

Ура!

Ответы [ 3 ]

4 голосов
/ 12 мая 2010

pthread_join, вероятно, внутренне реализован как ожидание семафора, который запускается при выходе из потока, либо при вызове pthread_exit, либо при выходе из его основной функции.

В любом случае, исходный код для glibc доступен, попробуйте поиск по коду Google (я видел некоторые информативные материалы там)

3 голосов
/ 12 мая 2010

Да, это общая идея. Для получения подробной информации о конкретной реализации взгляните на glibc .

1 голос
/ 22 марта 2012

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

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

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

Контекст потока может иметь небольшое поле, в котором завершающий поток может поместить свой статус выхода. (void * возвращается pthread_exit или возвращением из функции потока.)

Контекст потока также может указывать состояние потока (еще не создано, работает, остановлено).

Может существовать примитив синхронизации, такой как условная переменная или семафор, который поток может kick после подготовки состояния завершения и указания, что он завершается.

Функция pthread_join может ожидать этого примитива синхронизации. По завершении ожидания функция может инициировать очистку ресурса для этого потока в дополнение к извлечению статуса.

Поток продолжает выполняться после сообщения о соединении. Для этого он должен продолжать иметь контекст со стеком. После этого система должна решить проблему чистой остановки потока в фоновом режиме.

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

В ядре планировщик может «съесть» поток. Поток может вызвать некоторую функцию в планировщике, которая никогда не возвращается после очистки большинства своих ресурсов. Он помечает поток как мертвый и переключает контекст на другой поток. Стек потока никогда не будет использоваться снова (так как эта функция никогда не вернется) и может быть восстановлен, а также его структура задачи и все оставшиеся элементы, связанные с ним.

...