c++ - 互斥锁出错了?

标签 c++ multithreading pthreads mutex

我正在尝试 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 的回答)是使用带互斥量的局部变量,我已经测试它可以完美地工作!

最佳答案

这不是线程问题 – 问题在于,尽管 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 + (1 + 2) + (1 + 2 + 3) 和线程 2,4 + (4 + 5) + ( 4 + 5 + 6)
除了他们不这样做——每次他们使用它时,Sum 可能已被其他线程修改。

因此线程 1 可能会计算 1 + ((1 + 4) + 2) + ((1 + 4) + 2 + 3) 或其他。

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

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

关于c++ - 互斥锁出错了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43110419/

相关文章:

c++ - 如何在 linux 中分析 pthread 互斥锁?

java - 除以减法 - 将余数除以减法?

c++ - 我怎样才能让 QtCreator 打破异常?

python - 在嵌入式 PyQt 应用程序中使用 QThread

Java : What happens if a Runnable that is being used in a thread is set to null?

C 中的并发 TCP 服务器调整其大小。

c++ - 在 C++ 中停止特定线程

iphone - Objective-C 和 C++ 中结构的大小

c++ - 使用 visual stdio2008 的线程

c++ - 结构中的 vector 不会让我 push_back