我是C语言中的多线程新手,我有这个问题。我写了以下代码:
#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上的Code :: Blocks中编译并运行了这段代码。
答案 0 :(得分:5)
您正在传递for
正在变化的变量的地址(i
),因此您受调度程序的支配。你应该传递一份副本。作为一种廉价而非完全犹太的方式:
pthread_create(&thread[i],&attr,test, (void*)i);
/* ... */
int i = (int)a;
答案 1 :(得分:2)
请注意,您将i
的地址作为参数传递给您的主题:
pthread_create(&thread[i],&attr,test,&i);
这意味着您的所有线程都将读取相同的变量i
以确定它们是哪个线程。也就是说,所有五个线程都将查看相同的变量以确定其线程号。因此,当i
循环中for
的值递增时,所有线程都会感知其线程号更改为使用新值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);
}
或者,您可以将i
投射到void*
并将其传递到:
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);
}
希望这有帮助!