我试图了解线程的工作原理。我有一些学校的例子。在这一个我必须弄清楚为什么这段代码不能正常工作。它的输出是:
Main: Creating thread 0
Main: Creating thread 1
Main: Creating thread 2
Main: Creating thread 3
Main: Creating thread 4
Main: Creating thread 5
Main: Creating thread 6
Main: Creating thread 7
Main: Creating thread 8
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
Thread 0: English: Hello World!
但每个帖子都应该用不同的语言说'Hello World'。这是我的代码。当函数pthread_create
中的第四个参数只是(void *) t
而不是指针时,它工作正常。但我知道正确的解决方案是(void *) &t
。可能我正在处理一些指针问题,但我只是看不出路......
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUM_THREADS 8
char *messages[NUM_THREADS + 1] =
{
"English: Hello World!",
"French: Bonjour, le monde!",
"Spanish: Hola al mundo",
"Klingon: Nuq neH!",
"German: Guten Tag, Welt!",
"Russian: Zdravstvytye, mir!",
"Japan: Sekai e konnichiwa!",
"Latin: Orbis, te saluto!",
"Cesky: Ahoj svete!"
};
void * helloThread ( void * threadid )
{
int *id_ptr, taskid;
sleep(1);
id_ptr = (int *) threadid;
taskid = *id_ptr;
printf("Thread %d: %s\n", taskid, messages[taskid]);
return(NULL);
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc, t;
for(t=0;t<=NUM_THREADS;t++) {
printf("Main: Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, helloThread, (void *) &t );
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
return (EXIT_FAILURE);
}
}
pthread_exit(NULL);
return ( 0 );
}
答案 0 :(得分:5)
有几件事是错的:
首先,你超越界限;循环应该说for(t = 0; t < NUM_THREADS; t++)
。
其次,你必须在结束进程之前加入或分离线程,所以最后说这个:
for(t = 0; t < NUM_THREADS; ++t) {
pthread_join(threads[t], NULL);
}
第三,您将相同的指针(即&t
)传递给所有线程。这不仅会给您带来错误的行为,而且还会因为竞争条件或解除引用悬挂指针而使您暴露于未定义的行为。相反,给每个线程都有自己的内存:
int q[NUM_THREADS]; /* dedicated storage for each thread! */
for(t = 0; t < NUM_THREADS; ++t) {
printf("Main: Creating thread %d\n", t);
q[t] = t;
rc = pthread_create(threads + t, NULL, helloThread, q + t);
/* ... */
}
(第四,你不应该以你终止主线程的方式调用pthread_exit
。这是不必要的,它阻止你从main()
返回通常的方式。)
答案 1 :(得分:1)
您正在t
中传递指向循环迭代器main()
的指针。
当循环增加迭代器的值时...运行的线程会看到当时的任何内容。由于你所有的线程都要在做任何事情之前等待一秒钟并且你从main()
退出而没有等待线程完成,你指向的东西不再有效,你看到的任何东西都将是未定义的行为。
答案 2 :(得分:0)
&t
将指针传递给线程的变量t
。由于每个线程都获得指向同一个变量(t
)的指针,因此每个线程中的值在任何给定时间都是相同的。
一个简单的解决方案:
pthread_t threads[NUM_THREADS];
int thread_ids[NUM_THREADS]; // array which will hold the ID of each thread
int rc, t;
for(t=0;t<NUM_THREADS;t++) { // fixed
printf("Main: Creating thread %d\n", t);
thread_ids[t] = t; // setting the thread id
rc = pthread_create(&threads[t], NULL, helloThread, (void *) &thread_ids[t] );
// notice that I use &threads_ids[t] instead of &t
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
return (EXIT_FAILURE);
}
}