2012-01-21 41 views
2

我试图理解线程是如何工作的。我有一些学校的例子。在这一个中,我必须弄清楚为什么这段代码无法正常工作。它的输出是这样的:C中的POSIX线程

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

回答

1

你传递的一个指针循环迭代tmain()

当循环增加迭代器的值时...您正在运行的线程可以看到当时的任何内容。由于所有线程都会在做任何事情之前等待一秒钟,并且您在不等待线程完成的情况下退出main(),您指向的内容不再有效,您看到的任何内容都将是未定义的行为。

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()返回。 )

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