std::поток в цикле приводит к неправильным результатам

#c #multithreading #stdthread

Вопрос:

Я работаю над программой, которая выполняется в цикле for. Поскольку аргументы и выходные данные для каждого вызова уникальны, я мог бы распараллелить вызовы внутри цикла. Однако это работает неправильно. Ниже приведен пример программы, иллюстрирующей эту проблему

 #include <iostream>
#include <cstdlib>
#include <thread>
#include <mutex>

void subProg1(intamp; ii, doubleamp; emod, doubleamp; prat);
using namespace std;


int main()
{
  int imax = 4;
  int ii;
  double emod[4];
  double prat[4];

  std::thread threadpointer[4];

  emod[0] = 10;
  emod[1] = 20;
  emod[2] = 30;
  emod[3] = 40;

  prat[0] = 0.1;
  prat[1] = 0.2;
  prat[2] = 0.3;
  prat[3] = 0.4;


  for (ii=0;ii<imax;ii  ) {
    cout<<" In main Program " <<endl;
    cout<<" count = : "<<ii<<" emod = : "<<emod[ii]<<" pRat = : "<<prat[ii]<<endl;
    threadpointer[ii] = std::thread(subProg1,ref(ii),ref(emod[ii]),ref(prat[ii]));
    //threadpointer[ii].join();
  }

  for (ii=0;ii<imax;ii  ) {
    threadpointer[ii].join();
  }
    

}

void subProg1(intamp; ii, doubleamp; emod, doubleamp; prat)
{
   cout <<" In SubProgram "<<endl;
   cout<<" count = : "<<ii<<" emod = : "<<emod<<" pRat = : "<<prat<<endl;
}
 

Результат этого прогона выглядит следующим образом

  In main Program
 count = : 0 emod = : 10 pRat = : 0.1
 In SubProgram
 In main Program
 count = : 1 emod = :  count = : 1 emod = : 20 pRat = : 0.2
10 pRat = : 0.1
 In SubProgram
 In main Program
 count = : 2 emod = : 20 pRat = : 0.2
 count = : 2 emod = : 30 pRat = : 0.3
 In SubProgram
 In main Program
 count = : 3 emod = : 40 pRat = : 0.4
 count = : 3 emod = : 30 pRat = :  In SubProgram
 count = : 2 emod = : 40 pRat = : 0.4
0.3
 

Я понимаю, что звонки будут несинхронизированы. Однако индекс и значения emod и prat, соответствующие этому индексу, также не совпадают. Правильные значения должны быть

 count = :0 emod = : 10 pRat = :0.1
count = :1 emod = : 20 pRat = :0.2
count = :2 emod = : 30 pRat = :0.3
count = :3 emod = : 40 pRat = :0.4
 

Интересно, чего мне не хватает. Любая помощь будет признательна

Комментарии:

1. Захват ii по значению, в противном случае, если ii захват по ссылке, на него влияет цикл in for.

2. Как говорит @rafix07, в вашем коде есть условие гонки, поскольку все созданные потоки пытаются получить доступ ii одновременно for с тем, как цикл изменяет его.

3. Спасибо. вот в чем была проблема

Ответ №1:

Не передавайте счетчик по ссылке, так как при увеличении main он также будет увеличиваться в потоке. Передайте его по значению.

 void subProg1(int ii, doubleamp; emod, doubleamp; prat);