Я новичок в многопоточности в Windows, поэтому у меня может возникнуть тривиальный вопрос: какой самый простой способ убедиться, что потоки выполняют цикл синхронно?
Я попытался передать общий массив Event
всем потокам и использовать WaitForMultipleObjects
в конце цикла для их синхронизации, но это привело к тупиковой ситуации после одного, а иногда и двух циклов. . Вот упрощенная версия моего текущего кода (всего с двумя потоками, но я бы хотел сделать его масштабируемым):
typedef struct
{
int rank;
HANDLE* step_events;
} IterationParams;
int main(int argc, char **argv)
{
// ...
IterationParams p[2];
HANDLE step_events[2];
for (int j=0; j<2; ++j)
{
step_events[j] = CreateEvent(NULL, FALSE, FALSE, NULL);
}
for (int j=0; j<2; ++j)
{
p[j].rank = j;
p[j].step_events = step_events;
AfxBeginThread(Iteration, p+j);
}
// ...
}
UINT Iteration(LPVOID pParam)
{
IterationParams* p = (IterationParams*)pParam;
int rank = p->rank;
for (int i=0; i<100; i++)
{
if (rank == 0)
{
printf("%dth iteration\n",i);
// do something
SetEvent(p->step_events[0]);
WaitForMultipleObjects(2, p->step_events, TRUE, INFINITE);
}
else if (rank == 1)
{
// do something else
SetEvent(p->step_events[1]);
WaitForMultipleObjects(2, p->step_events, TRUE, INFINITE);
}
}
return 0;
}
(Я знаю, что смешиваю C и C ++, на самом деле это унаследованный код C, который я пытаюсь распараллелить.)
Читая документацию в MSDN, думаю, это должно сработать. Однако поток 0 печатает только один раз, иногда дважды, а затем программа зависает. Это правильный способ синхронизации потоков? Если нет, что бы вы порекомендовали (действительно ли в MFC нет встроенной поддержки барьера?).
ИЗМЕНИТЬ : это решение НЕПРАВИЛЬНО , даже включая исправление Алессандро . Например, рассмотрим следующий сценарий:
Таким образом, остается вопрос: как можно безопасно гарантировать, что потоки остаются в синхронизированном состоянии. ?