2

我有测试代码:

#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);

---> 好的

为什么在上述情况下会出现段错误?感谢帮助 !!!

4

1 回答 1

1

If you posted all your code, you have a race condition.

main is synchronized with the start of worker but not worker2.

That is, main is trying to join th_worker2 before worker has had a chance to invoke pthread_create and set up th_worker2 with a valid [non-null] value.

So, th_worker2 will be invalid until the second pthread_create completes, but that's already too late for main. It has already fetched th_worker2, which has a NULL value and main will segfault.

When you add the join for th_worker, it works because it guarantees synchronization and no race condition.


To achieve this guarantee without the join, have main do:

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;
}

An even better way to do this is to add an extra variable. With this, the first loop is not needed [but I've left it in]:

#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;
}
于 2015-12-08T02:51:44.540 回答