c++多线程参数问题

c++ Multi-threading Argument Issues

本文关键字:问题 参数 多线程 c++      更新时间:2023-10-16

我正试图将一系列参数传递到不同的c++线程中。当NumThreads==1时,程序运行良好,但当NumThreads>1时,我传递给函数的p参数在线程中不正确。我是不是在线程构造函数中遗漏了什么,并且没有按值传递p?

创建线程的位置:

int NumThreads = 2;
std::thread t[numSamplePoints];
std::mutex dataLock;
for( int i = 0 ; i < numSamplePoints ; i++)
{
  // Prevent more than NumThreads from running at once
  if( i > NumThreads && t[i-NumThreads].joinable() )
  {
    t[i - this->NumThreads].join();
  }
  // Set and Check Input Parameters
  double p[3];
  srcPoints->GetPoint(i , p);
  if( i < 3 )
  {
    cout<< "OUTTHREAD " << p[0] << " " << p[1] << " " << p[2] <<endl;
    cout<< "src: " << Id << " index: " << i <<endl;
  }
  t[i] = std::thread(&MyClass::MyFunction, this, &dataLock, i, Id, p);
}

被调用的成员函数:

void MyClass::MyFunction(std::mutex *dataLock, int sampleIndex, int Id, double srcPoint[3])
{
  dataLock->lock();
  if( sampleIndex < 3)
  {
    cout<< "IN THREAD " << srcPoint[0] << " " << srcPoint[1] << " " << srcPoint[2] <<endl;
    cout<< "src: " << sourceId << " index: " << sampleIndex <<endl;
  }
  dataLock->unlock();
}

前三个线程的控制台输出:{

OUTTHREAD 45.7694 1.06209 -60.9628
src: 0 index: 0
OUTTHREAD 48.6044 -5.40514 -54.7663
src: 108 index: 1
OUTTHREAD 52.505 9.00298 -47.0499
src: 216 index: 2
IN THREAD 52.505 9.00298 -47.0499
src: 0 index: 0
IN THREAD 52.505 9.00298 -47.0499
src: 108 index: 1
IN THREAD 52.505 9.00298 -47.0499
src: 216 index: 2

因此,ID和示例索引被正确地传递给线程,但srcPoint如何对所有三个线程都相同?!?

通过将指向本地变量的指针传递给线程并允许变量在使用之前超出范围,可以调用未定义的行为。

C样式数组从不按值传递。一个声明以数组类型为参数的函数实际上使用了一个指针:

void MyClass::MyFunction(std::mutex *dataLock, int sampleIndex, int Id, double srcPoint[3])

相当于

void MyClass::MyFunction(std::mutex *dataLock, int sampleIndex, int Id, double* srcPoint)

在这种情况下,p数组是for循环作用域的本地数组,当传递给thread构造函数时,它隐式地衰减为指向其第一个元素的指针。一旦循环的每次迭代完成,p就会超出范围并被销毁,但线程仍然有一个指向它曾经驻留的内存的指针。

修复此问题的最佳选项是在循环中用std::array<double, 3> p替换double p[3],并使MyClass::MyFunction采用参数std::array<double, 3> srcPoint而不是double srcPoint[3]。与原始C样式数组不同,std::array可以通过值传递,并实现您期望的复制语义。