我正在尝试Pthreads及其非常基本的程序:我在所有线程中有两个共享变量(声明为全局)
long Sum = 0;
long Sum1 = 0;
pthread_mutex_t mutexLock = PTHREAD_MUTEX_INITIALIZER;
在线程函数中:
for(int i=start; i<end; i++) //start and end are being passed to thread and they are being passed correctly
{
pthread_mutex_lock(&mutexLock);
Sum1+=i;
Sum+=Sum1;
pthread_mutex_unlock(&mutexLock);
}
main()以防需要参考:
int main()
{
pthread_t threadID[10];
for(int i=0; i<10; i++)
{
int a = (i*500) + 1;
int b =(i + 1)*500;
ThreadStruct* obj = new ThreadStruct(a,b);
pthread_create(&threadID[i],NULL,ThreadFunc,obj);
}
for(int i=0; i<10; i++)
{
pthread_join(threadID[i], NULL);
}
cout<<"Sum: "<<Sum<<endl;
cout<<"Sum1: "<<Sum1<<endl;
return 0;
}
输出
总和:40220835000 Sum1:12502500
再次运行
总和:38720835000 Sum1:12502500
再次运行
总和:39720835000 Sum1:12502500
问题
为什么我在每次迭代中为Sum
获取不同的值?
休息整个代码工作正常,Sum1的输出是正确的 - 无论我运行代码多少次。 (唯一的问题是总和)。我在使用互斥锁时做错了吗?
更新
如果我在其详细解答中指定了 @molbdnilo 这样的局部变量,那么这个问题就解决了。一开始,我认为互斥量在这里是无关紧要的,但我测试了很多次并观察了不使用互斥锁导致此问题再次发生的情况。所以,这个问题的解决方案(礼貌:通过 @molbdnilo 回答)是使用局部变量WITH mutex,我已经测试它完美地工作了!
答案 0 :(得分:4)
这不是线程问题 - 问题在于即使Sum1
的添加顺序无关紧要,Sum
的添加顺序也是如此。
考虑更短的和1 + 2 + 3和以下交错
1:
Sum1 = 1 + 2 = 3
Sum = 0 + 3 = 3
Sum1 = 3 + 3 = 6
Sum = 3 + 6 = 9
2:
Sum1 = 1 + 3 = 4
Sum = 0 + 4 = 4
Sum1 = 4 + 2 = 6
Sum = 4 + 6 = 10
3:
Sum1 = 2 + 3 = 5
Sum = 0 + 5 = 5
Sum1 = 5 + 1 = 6
Sum = 5 + 6 = 11
你可以通过让线程独立计算自己的和和并在之后添加它们来解决这个问题。
(请注意,此处没有并发突变,因此锁定任何内容都无法发挥作用。)
有关更具体的示例,请将程序限制为两个线程,将总和从1到6
然后,您有一个计算1 + 2 + 3
的线程和一个正在执行4 + 5 + 6
的线程。
乍一看,第一个线程还应计算1 + (1 + 2) + (1 + 2 + 3)
和线程2,4 + (4 + 5) + (4 + 5 + 6)
除非他们不在 - 每次使用它时,Sum
可能已经被另一个线程修改过。
因此,线程1可以计算1 + ((1 + 4) + 2) + ((1 + 4) + 2 + 3)
或其他内容。
当您使用局部变量时,您可以保持每个线程的结果独立于其他线程。
(我认为这个问题很好地说明了共享可变状态如何以一种意想不到的方式使事情复杂化。)