2013-01-02 57 views
2

我是新来C多线程,我有这个问题。我写了下面的代码:多线程C程序中线程ID错误?

#include <stdio.h> 
#include <pthread.h> 
#include <unistd.h> 

pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER; 
pthread_attr_t attr; 

void* test(void *a) 
{ 
    int i=*((int *)a); 
    printf("The thread %d has started.\n",i); 
    pthread_mutex_lock(&m); 
    sleep(1); 
    printf("The thread %d has finished.\n",i); 
    pthread_mutex_unlock(&m); 
    pthread_exit(NULL); 

} 

int main() 
{ 
    int i=0; 
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); 
    pthread_t thread[5]; 

    for (i=0;i<5;i++) 
     pthread_create(&thread[i],&attr,test,&i); 

    for (i=0;i<5;i++) 
     pthread_join(thread[i],NULL); 
    return 0; 
} 

为什么我得到这样的值:

The thread 0 has started. 
The thread 0 has started. 
The thread 5 has started. 
The thread 5 has started. 
The thread 0 has started. 
The thread 0 has finished. 
The thread 0 has finished. 
The thread 5 has finished. 
The thread 5 has finished. 
The thread 0 has finished. 

The thread 1 has started. 
The thread 2 has started. 
The thread 5 has started. 
The thread 4 has started. 
The thread 0 has started. 
The thread 1 has finished. 
The thread 2 has finished. 
The thread 5 has finished. 
The thread 4 has finished. 
The thread 0 has finished. 

甚至:

The thread 0 has started. 
The thread 0 has started. 
The thread 0 has started. 
The thread 0 has started. 
The thread 0 has started. 
The thread 0 has finished. 
The thread 0 has finished. 
The thread 0 has finished. 
The thread 0 has finished. 
The thread 0 has finished. 

等等,当我的预期得到:

The thread 0 has started. 
The thread 1 has started. 
The thread 2 has started. 
The thread 3 has started. 
The thread 4 has started. 
The thread 0 has finished. 
The thread 1 has finished. 
The thread 2 has finished. 
The thread 3 has finished. 
The thread 4 has finished. 

只有当我把usleep(10)thread_create后,我能得到一些“正常”值。

我编译和在Unix上运行的代码:: Blocks的验证码。

回答

2

注意,你是传递的i地址作为参数传递给你的线程:

pthread_create(&thread[i],&attr,test,&i); 

这意味着,所有的线程都可以读取相同的变量i以确定它们是哪个线程。也就是说,所有五个线程都会查看同一个变量来确定它们的线程号。因此,当在你的for循环i增量值,所有的线程会认为他们的线程数更改为使用的i新值。这就是为什么你有时看到5作为线程号码,也解释了你经常跳过数字或看到太多重复的事实。

为了解决这个问题,你需要给每个线程的i自己的拷贝。例如,你可以做这样的事情:

int* myI = malloc(sizeof(int)); 
*myI = i; 
pthread_create(&thread[i], &attr, test, myI); 

,然后让线程释放指针终止前:

void* test(void *a) 
{ 
    int i=*((int *)a); 
    printf("The thread %d has started.\n",i); 
    pthread_mutex_lock(&m); 
    sleep(1); 
    printf("The thread %d has finished.\n",i); 
    pthread_mutex_unlock(&m); 
    pthread_exit(NULL); 
    free(a); 
} 

或者,你可以投ivoid*,并通过在:

pthread_create(&thread[i],&attr,test, (void*)i); 

如果你这样做,你会让这些线程直接将它们的参数转换回int而不是int*

void* test(void *a) 
{ 
    int i = (int)a; 
    printf("The thread %d has started.\n",i); 
    pthread_mutex_lock(&m); 
    sleep(1); 
    printf("The thread %d has finished.\n",i); 
    pthread_mutex_unlock(&m); 
    pthread_exit(NULL); 
} 

希望这有助于!

5

你传递一个变量的地址for正在改变(i),所以你在调度的摆布。你应该只是通过一份副本。作为一种廉价的,不完全 - 犹太方式:

pthread_create(&thread[i],&attr,test, (void*)i); 

/* ... */ 

int i = (int)a; 
+0

你的意思是我应该传似Ĵ另一个变量= i和传递? –

+0

@BillSkiadas看到我的编辑,我张贴了一些代码。 – cnicutar