我现在正在学习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”,我创建的每个线程都有一行!
〜DESI
答案 0 :(得分:3)
在创建的10个线程中的任何一个线程都有机会运行之前,for循环可能会迭代10次。在这种情况下,每个线程的*thread_number
值为10(因为它是指向具有单个值的单个内存位置的指针)。
如果您没有将指针i
传递给pthread_create
,那么int
的值最终将被视为地址,因此当您在{{{{}}中取消引用它时1}},你正在访问一些任意的内存位置,其内容可能是未定义的。你很幸运,在那种情况下你不会发生分裂。
如果您希望在每个帖子中看到thread_main
的正确值,您需要在调用*thread_number
之前malloc
新int
并为其指定当前值pthread_create
,如此:
i
当然,当线程完成后,你需要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
答案 1 :(得分:3)
首先关闭*(int *)thread_number是指针的东西 - 当你只有thread_number时,'奇怪的数字'是 main 函数中指向'i'的指针(除非我错误的是,它们应该是一次运行程序的相同数字(所以10个线程中的每一个都应该具有相同的“在线程号[数字]”))。
你需要明白这些是重复5的指针才有意义 - 每个线程都使用 main 函数中的相同底层i - 它没有被复制用于每个新线程,所以当i在 main 函数中递增时,这反映在 thread_main 函数中的thread_number中。
最后一个难题是每个新线程的设置时间然后上下文切换(更改哪个线程实际运行)不是立即的,所以在你的情况下,for循环在新创建的线程之前运行5次实际上是运行的(在本书的情况下,for循环在上下文切换之前运行8次),然后每个线程查看相同的底层i值,现在为5。
答案 2 :(得分:1)
首先,竞争条件是一件坏事。该程序不按预期工作。竞争条件意味着该程序旨在破坏。
在这种情况下,您的所有线程看起来都是共享变量i
。您正在向他们传递对单个共享变量的引用,当他们碰巧安排时,他们会尝试报告这些变量。