我有测试代码:
#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----%dn", 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-----%dn", 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);
--->OK
为什么在上述情况下会出现分段故障错误?谢谢你的帮助!!!
如果您发布了所有代码,则存在竞争条件。
main
与worker
的开始同步,但不worker2
。
也就是说,在worker
有机会调用pthread_create
并设置具有有效[非null]值的th_worker2
之前,main
正试图加入th_worker2
。
因此,在第二个pthread_create
完成之前,th_worker2
将是无效的,但对于main
来说已经太晚了。它已经获取了具有NULL值的th_worker2
,并且main
将segfault。
当您为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----%dn", 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-----%dn", 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;
}