Использование потоков для распараллеливания

Рейтинг: 0Ответов: 1Опубликовано: 20.03.2011

Пишу на C++ Builder. Имеется динамический список объектов. Для каждого объекта рассчитывается оценка. Сейчас такой расчет для всех объектов списка реализован в цикле. Поскольку алгоритм расчета оценки использует только данные конкретного объекта, имеет смысл выполнять его одновременно для нескольких объектов сразу в параллельных потоках. Что я собственно и попробовал сделать:

cEstimationThread * pFirstThread=new cEstimationThread(true);
cEstimationThread * pSecondThread=new cEstimationThread(true);

for(cChromosome * curChromosome=startChromosome;curChromosome;)
{
    if(!pFirstThread->bRunning)
    {
        pFirstThread->SetValuesForEstimation(
            curChromosome,
            arrUnitSets,
            arrUncertSets,
            iNumOfVars,
            iNumOfSets,
            iNumOfUnitSets,
            iCoverWeight);
        pFirstThread->Resume();
        curChromosome=curChromosome->next;
    }
    if(curChromosome)
    {
        if(!pSecondThread->bRunning)
        {
            pSecondThread->SetValuesForEstimation(
                curChromosome,
                arrUnitSets,
                arrUncertSets,
                iNumOfVars,
                iNumOfSets,
                iNumOfUnitSets,
                iCoverWeight);
            pSecondThread->Resume();
            curChromosome=curChromosome->next;
        }
    }
    while(pFirstThread->bRunning&&pSecondThread->bRunning);
}
while(pFirstThread->bRunning||pSecondThread->bRunning);

pFirstThread->FreeOnTerminate=true;
pSecondThread->FreeOnTerminate=true;

pFirstThread->Terminate();
pSecondThread->Terminate();

Здесь создаются два потока pFirstThread и pSecondThread, затем в первый поток заносится ссылка на очередной объект curChromosome, указатели на динамические массивы arrUnitSets, arrUncertSets (используются только для чтения) и еще несколько переменных для расчета (заносятся по значению, используются только для чтения). Потом первый поток запускается на выполнение. Затем, следующий объект заносится во второй поток и т.д.

После этого в строке while(pFirstThread->bRunning&&pSecondThread->bRunning), как мне кажется, я реализовал ожидание выполнения обоих потоков (переменная bRunning в начале выполнения кода потока принимает значение true, а после выполнения false). Как только список объектов заканчивается, потоки уничтожаются.

Код, как ни странно :), оказался нерабочим. При пошаговой отладке происходит что-то странное: то выполняется код основного потока, то pFirstThread, при чем непонятно, чем это определяется.

В связи с этим два вопроса:

  1. как в случае с двумя процессорами ОС (WinXP) определяет, какой поток запустить, а какой приостановить (все равно же они не будут выполняться одновременно)?
  2. можно ли таким образом синхронизировать выполнение потоков: while(pFirstThread->bRunning&&pSecondThread->bRunning)?

Ответы

▲ 2
  1. Потоки выполняются одновременно :-) Если даже процессор один - тогда они будут на микроуровне попеременно выполняться. На макро (для пользователя) - как будто одновременно.
  2. лучше - WaitForSingleObject или WaitForMultipleObject, IMHO. Или хотя бы объявить bRunning как volatile. Как и все переменные, которые могут быть модифицированы из нескольких потоков.