Почему присоединение к одному потоку приводит к вызову нескольких потоков? - PullRequest
0 голосов
/ 11 апреля 2019

Я изучаю потоки и программирую с потоками на C в Linux. Что я понимаю, так это то, что присоединение к потоку просто вызывает поток и ожидает его выполнения, как ожидание запуска дочернего процесса. Но я не уверен, почему, когда я пытаюсь присоединиться к одному потоку, он вызывает два потока!

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

void *start1()
{
    printf("Hello from Thread 1\n");

}

void *start2()
{
    printf("Hello from Thread 2\n");
}

void main()
{
    pthread_t t1,t2;

    pthread_create(&t1,NULL,start1,NULL);
    pthread_create(&t2,NULL,start2,NULL);
    pthread_join(t1,NULL); 
}

Когда я запускаю код, вот вывод:

[root@localhost]# ./a.out 
Hello from Thread 1
Hello from Thread 2

Я ожидал, что он вызовет только код для start1.

Ответы [ 3 ]

6 голосов
/ 11 апреля 2019

pthread_join ожидает завершения потока, а pthread_create создает и запускает поток независимо от того, присоединяетесь вы к нему или нет.

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

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

Если по какой-то причине вы хотите, чтобы запускался только один поток, вам следует либо запустить только один поток (очевидно :)), либо использовать какой-либо механизм синхронизации (например, mutex или * 1014).* условная переменная ), которая заставит второй поток ожидать выполнения какого-либо условия перед выполнением своей работы.

3 голосов
/ 11 апреля 2019

Функция pthread_join просто заставляет поток, вызвавший pthread_join, ждать, пока поток, к которому он присоединится, завершит выполнение. Пока поток, который ввел main, ожидает завершения потока 1, потоки 1 и 2 могут выполняться.

Однако в коде есть условие гонки. Он никогда не ждет окончания потока 2. Таким образом, результат может быть непредсказуемым. Например, поток, вызвавший main, может вернуться из main и завершить процесс до того, как у потока 2 появится шанс начать работу.

0 голосов
/ 11 апреля 2019

следующий предложенный код:

  1. чисто компилирует
  2. выполняет желаемую функциональность
  3. правильно ожидает завершения потока (ов) до выхода из программы
  4. использует правильную подпись для thread функций
  5. правильно выходит из thread функций
  6. правильно обрабатывает параметр функции для каждой функции потока
  7. не включает заголовочные файлы, содержимое которых не используется

и теперь предложенный код:

#include <pthread.h>
#include <stdio.h>
//#include <unistd.h>
//#include <stdlib.h>

void *start1( void * arg)
{
    (void)arg;
    printf( "Hello from Thread 1\n" );
    pthread_exit( NULL);
}

void *start2( void* arg)
{
    (void)arg;
    printf( "Hello from Thread 2\n" );
    pthread_exit( NULL );
}

int main( void )
{
    pthread_t t1,t2;

    pthread_create( &t1, NULL, start1, NULL );
    pthread_create( &t2, NULL, start2, NULL );
    pthread_join( t1, NULL ); 
    pthread_join( t2, NULL );
}
...