2014-11-21 3 views
2

Я работаю над проектом с определенным пользователем количеством потоков, в котором я использую 7 на данный момент. У меня есть цикл while, который выполняется в каждом потоке, но мне нужны все потоки, чтобы ждать друг друга в конце цикла while. Трудность в том, что некоторые из потоков не все заканчиваются одинаковым количеством раз в цикле.В то время как синхронизация цикла

void *entryFunc(void *param) 
{ 
    int *i = (int *)param; 
    int nextPrime; 
    int p = latestPrime; 
    while(latestPrime < testLim) 
    { 

     sem_wait(&sem); 
     nextPrime = findNextPrime(latestPrime); 
     if(nextPrime != -1) 
     { 
      latestPrime = nextPrime; 
      p = latestPrime; 
     } 
     else 
     { 
      sem_post(&sem); 
      break; 
     } 

     sem_post(&sem); 
     if(p < 46341) 
     { 
      incrementNotPrimes(p); 
     } 
/* 
     sem_wait(&sem2); 
     doneCount++; 
     sem_post(&sem2); 

     while(go != 1); 

     sem_wait(&sem2); 
     doneCount--; 
     //sem_post(&sem3); 
     sem_post(&sem2); 
*/ 
    } 
    return NULL; 
} 

, где фрагмент кода закомментирован, является частью моей последней попытки решить эту проблему. Именно там все функции должны ждать друг друга. У меня такое чувство, что я пропустил что-то простое.

+0

Вам нужны потоки, чтобы ждать друг друга после каждого завершения цикла while? В этом случае вы можете поставить семафор в ожидании сразу после цикла while. – VAndrei

+0

Используйте вместо барьера вместо семафора. – didierc

ответ

0

Как я уже упоминал в комментариях, для такого рода ситуаций вы должны использовать барьер вместо семафора, так как его проще реализовать (барьеры были разработаны именно для решения этой проблемы). Тем не менее, вы все равно можете использовать семафор с небольшим количеством арифметики : ваша цель состоит в том, чтобы все потоки выполняли один и тот же путь кода, но каким-то образом последний поток для завершения своей задачи должен разбудить все остальные потоки. Одним из способов достижения этого является наличие в конце функции атомарный счетчик, который каждый поток будет уменьшаться, и если счетчик достигнет 0, поток просто вызывает столько раз sem_post, сколько необходимо, чтобы освободить все ожидающие потоки, вместо этого выдачи sem_wait как других.

Второй способ, на этот раз с использованием только семафора, также возможен. Поскольку мы не можем отличить последний поток от остальных, все потоки должны выполнять одни и те же операции с семафором, т. Е. Пытаться освободить всех, но и дождаться последнего. Таким образом, идея состоит в том, чтобы инициализировать семафор до (1-n)*(n+1), так что каждый из первых потоков n-1 не смог просыпать своих друзей с n+1 звонками до sem_post, но все равно работает на получение семафора точно в 0. Затем последний поток будет делать то же самое, нажав значение семафора на n+1, тем самым освободив заблокированные потоки и оставив место для него также для выполнения своего sem_wait и быть выпущенным немедленно.

void *entryFunc(void *param) 
{ 
    int *i = (int *)param; 
    int nextPrime; 
    int p = latestPrime, j; 
    while(latestPrime < testLim){ 
    nextPrime = findNextPrime(latestPrime); 
    if(nextPrime != -1) 
    { 
     latestPrime = nextPrime; 
     p = latestPrime; 
    } 
    if(p < 46341) 
    { 
     incrementNotPrimes(p); 
    } 
    } 
    for (j=0;j<=THREAD_COUNT;j++) 
    sem_post(&sem); 
    sem_wait(&sem); 
    return NULL; 
} 

Проблема такого подхода заключается в том, что он не имеет дело с тем, как семафор должен быть сброшен в между применениями (если ваша программа должна повторить этот механизм, он должен сбросить значение семафора, поскольку оно в конечном итоге будет 1 после того, как этот код был успешно выполнен).

1

Если ваша проблема в том, что в каждом потоке цикл while имеет различное количество итераций, а потоки никогда не достигают точки синхронизации после выхода из цикла, вы можете использовать барьер. Проверьте here для примера.

Однако после выхода из каждой нити вам необходимо уменьшить количество потоков на барьере. Ожидание у барьера закончится после кол-во количество потоков достигло этой точки.

Поэтому вам нужно обновлять объект барьера каждый раз, когда заканчивается нить. И убедитесь, что вы делаете это атомарно.

Смежные вопросы