2

我现在正在学习 POSIX 线程,但我想这只是一个关于多线程的一般问题,所以我希望任何人都可以帮助我。我正在研究的书中有这个例子,它演示了一个竞争条件:

void *thread_main(void *thread_number) {
    printf("In thread number %d.\n", *(int *)thread_number);
}

void main() {
    int i = 0;
    pthread_t thread;

    for( i = 0; i < 10; i++ ) {
        printf("Creating thread %d.\n");
        pthread_create(&thread, 0, thread_main, &i);
        printf("Created thread %d.\n");
    }
}

关于这个,有几件事我不明白。首先,“在线程号 5 中”。被打印了很多次,即使它不应该在线程号 5 中。在书中,示例显示线程 8 被打印了很多次。我也不明白说的部分*(int *)thread_number。我尝试将其更改为仅 thread_number,但这只是一遍又一遍地给了我奇怪的数字。

这本书并没有真正解释这一点。有人可以清楚地解释这里发生了什么吗?我不明白为什么它不打印如下内容:

> Creating thread 1.
> In thread number 1.
> Created thread 1.
> Creating thread 2.
> In thread number 2.
> Created thread 2.

我知道这是因为它是多线程的“在线程号 x 中”。部分将在不同的时间出现,但我真的不明白为什么我创建的每个线程都没有 10 个“在线程编号 x”中一行!

~德西

4

3 回答 3

3

在创建的 10 个线程中的任何一个有机会运行之前,for 循环可能会迭代 10 次。在这种情况下,每个线程的值*thread_number将是 10(因为它是指向具有单个值的单个内存位置的指针)。

如果您不传递指向 to 的指针ipthread_create那么最终的值将int被视为地址,因此当您在 中取消引用它时thread_main,您正在访问某个任意内存位置,其内容可能未定义。你很幸运,在这种情况下你没有出现段错误。

如果您想*thread_number在每个线程中查看正确的值,则需要在调用之前malloc创建一个 new并将其分配给 的当前值,如下所示:intpthread_createi

for( i = 0; i < 10; i++ ) {
    int *thread_count = malloc(sizeof(int));
    *thread_count = i;
    printf("Creating thread %d.\n", i);
    pthread_create(&thread, 0, thread_main, thread_count);
    printf("Created thread %d.\n", i);
}

当然,free当线程完成时你需要内存,如下所示:

void *thread_main(void *thread_number) {
    printf("In thread number %d.\n", *(int *)thread_number);
    free(thread_numbr);
}
于 2009-01-06T12:13:29.803 回答
3

首先 *(int *)thread_number 是指针的东西——当你只有 thread_number 时,“奇怪的数字”是函数中指向“i”的指针地址(除非我弄错了,否则它们都应该是程序的单次运行具有相同的编号(因此 10 个线程中的每一个都应该具有相同的“线程编号 [编号]”))。

您需要了解这些是重复的 5 的指针才有意义 - 每个线程都在使用来自main函数的相同底层 i - 它不是为每个新线程复制的,所以当 i 在main函数,这反映在thread_main函数中的 thread_number 上。

难题的最后一块是每个新线程的设置时间以及上下文切换(更改实际运行的线程)不是立即的,因此在您的情况下,for循环在新创建的线程实际运行之前运行 5 次(在本书的例子中,for 循环在上下文切换之前运行了 8 次),然后每个线程查看相同的底层 i 值,现在是 5。

于 2009-01-06T12:27:26.220 回答
1

首先,竞争条件是一件坏事。该程序不应该像您期望的那样工作竞争条件意味着程序旨在中断。

在这种情况下,您的所有线程似乎都在共享变量i。您正在向他们传递对单个共享变量的引用,当他们碰巧被安排时,他们会尝试报告该变量。

于 2009-01-06T12:13:02.177 回答