互斥体出错了?

Mutex gone wrong?

本文关键字:错了 出错      更新时间:2023-10-16

我正在尝试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 总 1: 12502500

再次运行

总和: 38720835000 总 1: 12502500

再次运行

总和: 39720835000 总 1: 12502500

问题

为什么我在每次迭代中都会获得不同的Sum值?其余整个代码工作正常,Sum1 的输出是正确的 - 无论我运行代码多少次。(唯一的问题是总和)。我在这里使用互斥锁做错了吗?

更新

如果我按照他详细的答案@molbdnilo指定的那样使用局部变量,这个问题就解决了。一开始,我认为互斥锁在这里无关紧要,但我多次测试了它,并观察到不使用互斥锁导致此问题再次出现的情况。因此,这个问题的解决方案(礼貌:@molbdnilo回答)是将局部变量与互斥体一起使用,我已经测试了它以完美工作!

这不是线程问题 - 问题是,即使Sum1的添加顺序无关紧要,但Sum的添加顺序却很重要。

考虑更短的总和 1 + 2 + 3 和以下交错

1:

Sum1 = 1 + 2 = 3
Sum = 0 + 3 = 3
Sum1 = 3 + 3 = 6
Sum = 3 + 6 = 9

阿拉伯数字:

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 + (1 + 2) + (1 + 2 + 3)和线程 2,4 + (4 + 5) + (4 + 5 + 6)
除了他们没有 - 每次他们使用它时,Sum可能已被另一个线程修改。

所以线程一可以计算1 + ((1 + 4) + 2) + ((1 + 4) + 2 + 3),或者别的什么。

使用局部变量时,可以使每个线程的结果独立于其他线程。

(顺便说一下,我认为这个问题很好地说明了共享可变状态如何以意想不到的方式使事情复杂化。