убедитесь, что потоки созданы и ждут перед трансляцией - PullRequest
1 голос
/ 14 декабря 2011

У меня есть 10 потоков, которые должны ожидать сигнала.До сих пор я просто выполнял 'sleep (3)', и это работало нормально, но есть ли более безопасный способ убедиться, что все потоки созданы и действительно ожидают.

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

Мне не хватает некоторого базового шаблона проектирования потоков?

Спасибоedit: фиксированные типы

edit: уточняющая информация ниже

В этом случае барьер не будет работать, потому что я не заинтересован в том, чтобы мои потоки ожидали, пока все потоки не будут готовы.Это уже происходит с 'cond_wait'.

Мне интересно, чтобы основная функция знала, когда все потоки готовы и ожидают.

//mutex and conditional to signal from main to threads to do work
mutex_t mutex_for_cond;
condt_t cond;

//mutex and conditional to signal back from thread to main that threads are ready
mutex_t mutex_for_back_cond;
condt_t back_cond;

int nThreads=0;//threadsafe by using mutex_for_cond

void *thread(){
    mutex_lock(mutex_for_cond);
    nThreads++;
    if(nThreads==10){
      mutex_lock(mutex_for_back_cond)
      cond_signal(back_cond);
      mutex_unlock(mutex_for_back_cond)
    }while(1){
      cond_wait(cond,mutext_for_cond);
      if(spurious)
        continue; 
      else
        break;
    }
    mutex_unlock(mutex_for_cond);
    //do work on non critical region data
}

int main(){
for(int i=0;i<10)
   create_threads;

while(1){
   mutex_lock(mutex_for_back_cond);
   cond_wait(back_cond,mutex_for_back_cond);
   mutex_unlock(mutex_for_back_cond);
   mutex_lock(mutex_for_cond);
   if(nThreads==10){
     break;
   }else{
     //spurious wakeup 
     mutex_unlock(mutex_for_cond);
   }
}
//now all threads are waiting
//mutex_for_cond is still locked so broadcast
cond_broadcast(cond);//was type here


}

Ответы [ 3 ]

3 голосов
/ 14 декабря 2011

Мне не хватает базового шаблона проектирования резьбы?

Да.Для каждого условия должна быть переменная, которая защищена сопутствующим мьютексом.Только изменение этой переменной указывается сигналами в условной переменной.

Вы проверяете переменную в цикле, ожидая условия:

mutex_lock(mutex_for_back_cond);
while ( ready_threads < 10 )
   cond_wait(back_cond,mutex_for_back_cond);
mutex_unlock( mutex_for_back_cond );

Кроме того, что вы пытаетесьСборка - это барьер.Это часто предварительно реализовано в библиотеках потоков, как pthread_barrier_wait.

2 голосов
/ 14 декабря 2011

API-интерфейсы с разумной многопоточностью имеют конструкцию barrier, которая делает именно это.

Например, с boost::thread вы бы создали такой барьер:

boost::barrier bar(10); // a barrier for 10 threads

, а затемкаждый поток будет ждать на барьере:

bar.wait();

барьер ждет, пока его ожидает указанное число потоков, а затем освобождает их всех сразу.Другими словами, как только все десять потоков будут созданы и готовы, они позволят всем им продолжить.

Это простой и разумный способ сделать это.API потоков, которые не имеют барьерной конструкции, требуют, чтобы вы делали это трудным путем, мало чем отличаясь от того, что вы делаете сейчас.

0 голосов
/ 14 декабря 2011

Вы должны связать некоторую переменную, которая содержит «состояние события», с условной переменной.Основной поток соответствующим образом устанавливает переменную состояния события непосредственно перед отправкой широковещательной рассылки.Потоки, которые заинтересованы в событии, проверяют переменную состояния события независимо от того, заблокированы ли они в условной переменной или нет.

С этим шаблоном основной поток не должен знать о точном состояниииз потоков - он просто устанавливает событие, когда это необходимо, а затем передает условие.Любые ожидающие потоки будут разблокированы, и все потоки, которые еще не ожидают, никогда не заблокируют переменную условия, потому что они заметят, что событие уже произошло до ожидания условия.Что-то вроде следующего псевдокода:

//mutex and conditional to signal from main to threads to do work
pthread_mutex_t mutex_for_cond;
pthread_cond_t cond;
int event_occurred = 0;

void *thread() 
{
    pthread_mutex_lock(&mutex_for_cond);
    while (!event_occurred) {
            pthread_cond_wait( &cond, &mutex_for_cond);
    }
    pthread_mutex_unlock(&mutex_for_cond);

    //do work on non critical region data
}

int main()
{
    pthread_mutex_init(&mutex_for_cond, ...);
    pthread_cond_init(&cond, ...);

    for(int i=0;i<10)
        create_threads(...);

    // do whatever needs to done to set up the work for the threads

    // now let the threads know they can do their work (whether or not
    //  they've gotten to the "wait point" yet)
    pthread_mutex_lock(&mutex_for_cond);
    event_occured = 1;
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex_for_cond);
}
...