2014-11-12 4 views
3

Я написал простую демонстрационную программу, чтобы понять функцию pthread_join().pthread_join() для асинхронных потоков

Я знаю, как использовать функцию pthread_condition_wait() разрешить асинхронное нарезание резьбы, но я пытаюсь понять, как я могу сделать подобную работу с помощью функции pthread_join().

В программе ниже я прохожу Thread 1s ID для Thread 2s функцию. Внутри Тема 2s function Я вызываю функцию pthread_join() и передаю в Тема 1s ID. Я ожидал, что это вызовет Thread 1 для запуска сначала, а затем для Thread 2 для запуска второй, но то, что я получаю, заключается в том, что они оба запускаются одновременно.

Является ли это потому, что только один поток может использовать pthread_join() функцию в то время, и что я уже использовал pthread_join() функцию, когда я называю его из основного потока?

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

void *functionCount1(); 
void *functionCount2(void*); 

int main() 
{ 

    /* 
     How to Compile 
     gcc -c foo 
     gcc -pthread -o foo foo.o 
    */ 

    printf("\n\n"); 

    int rc; 
    pthread_t thread1, thread2; 

    /* Create two thread --I took out error checking for clarity*/ 
    pthread_create(&thread1, NULL, &functionCount1, NULL) 
    pthread_create(&thread2, NULL, &functionCount2, &thread1) 

    pthread_join(thread1, NULL); 
    pthread_join(thread2, NULL); 

    printf("\n\n"); 
    exit(0); 
} 

void *functionCount1() 
{ 

    printf("\nFunction 1"); 
     sleep(5); 
    printf("\nFunction 1"); 

    return(NULL); 
} 

void *functionCount2(void* argument) 
{ 

    pthread_t* threadID = (pthread_t*) argument; 

    pthread_join(*threadID, NULL); 

    printf("\nFunction 2"); 
     sleep(5); 
    printf("\nFunction 2"); 

    return(NULL); 
} 

Выход:

enter image description here

ответ

6

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

Что происходит, когда вы вызываете pthread_join(), вызывающий абонент ждет потока, с которым соединение завершается. Таким образом, основной поток ждет thread1 для завершения, а затем для thread2. Но в то время как главный ждет thread1, thread2, возможно, закончил выполнение и уже завершен. В этом случае pthread_join(thread2, NULL); немедленно вернется.

У вас возникла большая проблема с кодом. Вы передаёте thread1 's ID на номер thread2. Но если thread1 закончил выполнение до начала thread2, то вы собираетесь использовать недопустимый идентификатор потока, , приводящий к неопределенному поведению. Другая проблема заключается в том, что ваш основной поток и thread2 оба пытались присоединиться к thread1. Короче говоря, pthread_join() не является подходящим инструментом для синхронизации между несколькими потоками. Как вы сказали, для этой цели вы используете условные переменные/мьютексы.

Я предлагаю, вы удалите pthread_join() из thread2, чтобы исправить неопределенное поведение, и если вы хотите последовательного выполнения потоков, то вы должны создавать потоки один за другим, и пусть их и ждать предыдущей нити прекратить (pthread_join()). Но при этом очень мало практического использования. Или пусть потоки ожидают условную переменную, прежде чем что-либо делать, и вы можете связать потоки в том порядке, в котором вы хотите использовать условные переменные.

+0

Я думаю, что проблема «основной причины» - это вызов 'pthread_join (thread1, NULL);' из 'main()': это приводит к возможности параллельного соединения, которое не определено. Удаление также должно устранить проблему с недопустимым значением идентификатора потока, так как thread1 останется недействительным до вызова из потока2. – dasblinkenlight

+0

@dasblinkenlight Это очень действительная точка. Я тоже обновлю это. Благодаря! –

3

Вы вызываете неопределенное поведение.страница людей: http://man7.org/linux/man-pages/man3/pthread_join.3.html

Joining with a thread that has previously been joined results in undefined behavior. 

Кроме того, первый поток может закончить exectution до второго потока. Если вы хотите что-то вроде этого, то лучше использовать pthread_cond_wait().

1

Из pthread_join man page (курсив мой):

Если несколько потоков одновременно пытаются присоединиться к одной и той же теме, результаты не определены. Если поток, вызывающий pthread_join(), отменяется, то целевой поток останется соединяемым (т. Е. Он не будет отсоединен).

кажется, что вы именно в этой ситуации, с основной нитью и нитью 2 и пытается pthread_join нити 1.

Вы должны четко определить для каждого потока один «владелец потока», который отвечает за его управления. Цепочка ответственности должна составлять иерархическое дерево нити (т.е. нет циклов или нескольких родителей).

Смежные вопросы