У меня есть тестовый код:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_t th_worker, th_worker2;void * worker2(void *data) {
for(int i = 0; i< 1000000; i++){
printf("thread for worker2----%d\n", i);
usleep(500);
}
}
void * worker(void *data){
pthread_create(&th_worker2, NULL, worker2, data);
for(int i = 0; i< 100; i++){
printf("thread for worker-----%d\n", i);
usleep(500);
}
}
void join(pthread_t _th){
pthread_join(_th, NULL);
}
В функции main (), если я вызову join (the_worker2):
int main() {
char* str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void*) str);
/* problem in here */
join(th_worker2);
return 1;
}
—> Ошибка сегмента
Еще я звоню:
join(the_worker);
join(th_worker2);
—> ОК
Почему ошибка сегмента в вышеуказанном случае?
Спасибо за помощь !!!
Если вы отправили все ваш код, у вас есть состояние гонки.
main
синхронизируется с началом worker
но не worker2
,
То есть, main
пытается присоединиться th_worker2
до worker
был шанс призвать pthread_create
и настроить th_worker2
с действительный [ненулевое] значение.
Так, th_worker2
будет недействительным до второго pthread_create
завершает, но это уже слишком поздно для main
, Он уже принес th_worker2
, который имеет значение NULL и main
будет сегфо
Когда вы добавляете соединение для th_worker
, это работает, потому что это гарантии синхронизация и нет состояние гонки.
Чтобы достичь этой гарантии без объединения, сделайте так:
int
main()
{
char *str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void *) str);
// give worker enough time to properly start worker2
while (! th_worker2)
usleep(100);
/* problem in here */
join(th_worker2);
return 1;
}
Еще лучший способ сделать это — добавить дополнительную переменную. При этом первый цикл не нужен [но я его оставил]:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int worker_running;
pthread_t th_worker;
int worker2_running;
pthread_t th_worker2;
void *
worker2(void *data)
{
// tell main we're fully functional
worker2_running = 1;
for (int i = 0; i < 1000000; i++) {
printf("thread for worker2----%d\n", i);
usleep(500);
}
return NULL;
}
void *
worker(void *data)
{
// tell main we're fully functional
worker_running = 1;
pthread_create(&th_worker2, NULL, worker2, data);
for (int i = 0; i < 100; i++) {
printf("thread for worker-----%d\n", i);
usleep(500);
}
return NULL;
}
void
join(pthread_t _th)
{
pthread_join(_th, NULL);
}
int
main()
{
char *str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void *) str);
// give worker enough time to properly start worker2
// NOTE: this not necessarily needed as loop below is better
while (! th_worker2)
usleep(100);
// give worker2 enough time to completely start
while (! worker2_running)
usleep(100);
/* problem in here (not anymore!) */
join(th_worker2);
return 1;
}
Других решений пока нет …