我有一个int array[100],我想要5个线程来计算所有数组元素的总和。

每个线程在其专用范围内迭代20个元素,并将总和写入全局sum变量。

这里需要互斥吗?由于所有线程都从独立的源读取数据,因此不需要同步。

for(i=offset; i<offset+range; i++){
  // not used pthread_mutex_lock(&mutex);
  sum += array[i];
  // not used pthread_mutex_unlock(&mutex);
}

这会导致无法预料的行为,还是OS实际处理了此问题?

在这种情况下,建议不要使用互斥锁吗?我注意到,如果没有这些算法,这些算法的运行速度会大大提高。

最佳答案

是的,您需要同步,因为所有线程都在同时修改sum。例子如下:

您有4个元素[a1, a2, a3, a4]和2个线程t1t2sum组成的数组。首先,让我们说t1获得值a1并将其添加到sum中。但这不是原子操作,因此他将sum的当前值(它的值为0)复制到他的本地空间,我们称它为t1_s,将其添加到a1,然后编写sum = t1_s。但同时t2做同样的事情,他将sum值(为0,因为t1尚未完成操作)获得到t2_s,添加a3并写入sum。因此,我们获得了由sum插入的a3a1 + a3值。这称为数据竞赛。

对此有多种解决方案:

  • 您可以像在代码中一样使用mutex,但是正如您提到的那样,它可能很慢,因为互斥锁很昂贵,并且所有其他线程都在等待它。
  • 创建一个数组(具有线程数的大小)以计算所有线程的局部和,然后在一个线程中对该数组进行最后的约简。无需同步。
  • 如果不使用数组,则为每个线程计算本地sum_local,最后使用互斥锁将所有这些总和添加到共享变量sum中。我想它将更快(但是需要检查)。

  • 但是,正如@gavinb所述,所有这些仅对大量数据有意义。

    关于c - pthread互斥锁的必要性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30150903/

    10-16 03:42