I am writing in C ++ Builder. There is a dynamic list of objects. For each object, an estimate is calculated. Now such a calculation for all objects in the list is implemented in a cycle. Since the estimation calculation algorithm uses only the data of a specific object, it makes sense to execute it simultaneously for several objects simultaneously in parallel streams. What I actually tried to do:

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(); 

Here, two threads are created, pFirstThread and pSecondThread , then the first stream contains a link to the next curChromosome object, pointers to the dynamic arrays arrUnitSets , arrUncertSets (used only for reading) and a few more variables for calculation (recorded by value, used only for reading). Then the first thread is launched for execution. Then, the next object is entered into the second stream, and so on.

After that, in the while(pFirstThread->bRunning&&pSecondThread->bRunning) line while(pFirstThread->bRunning&&pSecondThread->bRunning) , I think I implemented waiting for both threads to execute (the bRunning variable at the beginning of the thread's code is true , and after it is false ). As soon as the list of objects ends, the threads are destroyed.

The code, oddly enough :), turned out to be inoperative. When step-by-step debugging happens, something strange happens: the code of the main thread is executed, then pFirstThread , but it is not clear how this is determined.

In this regard, two questions:

  1. How in the case of two OS processors (WinXP) determines which thread to start and which one to suspend (they will not run at the same time anyway)?
  2. Is it possible to synchronize the execution of threads in this way: while(pFirstThread->bRunning&&pSecondThread->bRunning) ?

    3 answers 3

    1. Threads are executed simultaneously :-) If even the processor is one, then they will be alternately executed at the micro level. At the macro (for the user) - as if at the same time.
    2. better - WaitForSingleObject or WaitForMultipleObject, IMHO. Or at least declare bRunning as volatile. Like all variables that can be modified from multiple threads.

      To synchronize threads, it is better to use special tools: mutexes and semaphores. Or variables with atomic access.

      You can do this, for example, in the cycle to start up streams and fall asleep, and wake up on an event that came at the end of another stream.

       do { // Пустить поток } while () // Ждать события 

        Thanks for the quick answers. I tried many options, but in the end came to nothing. As I understand it, WaitForMultipleObjects allows you to control the access of threads to some critical section. My task is set so that the whole program is a critical section, and the fact that inside the stream class is not a critical section. Maybe I do not understand the principle itself.

        Here is my Execute function:

         void __fastcall cEstimationThread::Execute() { EstimateFitnessesOfIndividuals(); } 

        EstimateFitnessesOfIndividuals () is a function for calculating data, implemented inside the streaming class.

        Here is the modified function where threads are created and called.

         void cBFGAConverter::EstimateFitnessesOfIndividuals(cChromosome *startChromosome) { int j, k; int iEstimation; int iNumOfCoveredUnitSets; cEstimationThread *pFirstThread = new cEstimationThread (true); cEstimationThread *pSecondThread = new cEstimationThread (true); HANDLE *hmy_threads = new HANDLE[2]; hmy_threads[0] = (void *) pFirstThread->Handle; hmy_threads[1] = (void *) pSecondThread->Handle; for (cChromosome * curChromosome = startChromosome; curChromosome;) { if (WaitForSingleObject((void *)pFirstThread->Handle, 0) == WAIT_OBJECT_0) { pFirstThread->SetValuesForEstimation( curChromosome, arrUnitSets, arrUncertSets, iNumOfVars, iNumOfSets, iNumOfUnitSets, iCoverWeight); pFirstThread->Resume (); curChromosome = curChromosome->next; } if (curChromosome) { if (WaitForSingleObject((void *)pSecondThread->Handle, 0) == WAIT_OBJECT_0) { pSecondThread->SetValuesForEstimation (curChromosome, arrUnitSets, arrUncertSets, iNumOfVars, iNumOfSets, iNumOfUnitSets, iCoverWeight); pSecondThread->Resume (); curChromosome = curChromosome->next; } } WaitForMultipleObjects (2, (void *const *) hmy_threads, false, INFINITE); } WaitForMultipleObjects (2, (void *const *) hmy_threads, true, INFINITE); pFirstThread->FreeOnTerminate = true; pSecondThread->FreeOnTerminate = true; pFirstThread->Terminate (); pSecondThread->Terminate (); return; }