#include<stdio.h>
#include<pthread.h>
#define NUM_THREAD (5)
int sum=0;
void* runner(void * param);
int main(int argc,char **argv){
pthread_t tid[NUM_THREAD];
pthread_attr_t attr;
pthread_attr_init(&attr);
for(i=0;i<NUM_THREAD;i++){
pthread_create(&tid[i],&attr,runner,NULL);
}
for(i=0;i<NUM_THREAD;i++){
pthread_join(tid[i],NULL);
}
printf("After threading %d",sum);
return 0;
}
void * runner(void *param){
for(int j = 0;j<10;j++) sum+=j;
pthread_exit(0);
}
输出:225
在下面的代码中,输出是225.但是正确的应该是45
我知道线程共享全局变量!所以这个功能应该正确输出。但是在内部添加sum = 0只能得到正确的输出。发生什么事在这里我不明白!
void * runner(void *param){
sum=0; // MY DOUBT
for(int j = 0;j<10;j++) sum+=j;
pthread_exit(0);
}
输出:45
答案 0 :(得分:4)
您有data race因为所有线程都访问/修改sum
而没有任何同步。所以45和225都是“错误的”。您可能会在不同的运行中看到不同的值。您需要synchronize访问sum
。
要注意的另一件事是你没有初始化attr
,而是传递给pthread_create
。您需要使用pthread_attr_init
初始化它。
答案 1 :(得分:3)
你正在处理的是竞争条件。对于每个系统,您将获得不同的输出。此代码的行为不是确定性的。
因为,当您在循环中创建每个线程时,将以无法知道的顺序调用迭代10次的runner
函数。
因此,期待45
或245
或其他任何事情是错误的。
当多个线程可以同时修改公共/共享数据时,竞争条件是一种不受欢迎的情况,因为它们可以访问它。 可以在系统与系统之间表现不同的调度程序可以在任何时间点在这5个线程之间切换。要获得确定性行为,需要通过Mutex或Semaphore等同步技术来解决这个问题。
Mutex是我最喜欢的。不是为你编写完整的代码,因为它没有必要的问题,我很懒。
执行相同操作的粗略步骤是:
创建线程的地方
在线程处理程序中,在您的情况下runner
函数,
因此,您的main
应包含pthread_mutex_init
,如果确实返回NULL,则可以继续。
在runner
函数中,pthread_mutex_lock(&lock);
应该是它做的第一件小事,然后是你的代码,然后在它返回之前最后pthread_mutex_unlock(&lock);
。
您创建的互斥锁可以被pthread_mutex_destroy
销毁。
很有趣!
答案 2 :(得分:1)
您正在从5个线程修改一个全局对象。一个线程将sum
的值增加45,所以当你将它乘以5时,你就有225。
这里的另一个问题是你修改了每个线程中的一个变量,这可能会导致比赛导致的一些混乱。