Что я могу использовать для ожидания создания всех потоков? - PullRequest
0 голосов
/ 28 мая 2018

Если я хочу создать 5 новых потоков в main и подождать, пока все пять этих потоков будут созданы, прежде чем начинать работу над ними, что мне следует использовать?

Я нашел pthread_cond_wait и, возможно, это то, что я должен использовать, но я не совсем уверен, как.Есть ли способ узнать, что тема была создана, и не войти в нее немедленно?

Спасибо.

1 Ответ

0 голосов
/ 29 мая 2018

Я не думаю, что это хорошая идея, которую вы описали: как бы вы справились с ситуацией, когда поток не был создан из-за каких-то ошибок?

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

Одно простое решение - использовать глобальную переменную, которая является счетчиком, и каждый раз, когда создается один из 5 потоков, счетчик увеличивается:

В любом случае, чтобы увидеть, правильно ли создан поток, вы можете использовать что-то вроде этого:

if ((err = pthread_create (&threadID, NULL, threadFunction, NULL))!=0)
{
    printf("some error\n");
}
else
{
    global_counter++;
}

Затем в каждой из функций потока используйте цикл, который ничего не делает, и чье условие циклапроверяет, меньше ли переменная счетчика, чем число потоков, которые вы хотите создать:

while (global_counter<5)
{
    ;
}
..../rest of the thread functions

ПРИМЕЧАНИЕ: это опасно, потому что, если вы не будете осторожны в выборе значений переменной, вы застрянете в 5 бесконечных циклах.

Также вам следует использовать мьютекс некоторого типа (возможно, мьютекс для чтения / записи), поскольку глобальный счетчик записывается одним потоком, а читается многими.

ВАЖНОЕ РЕДАКТИРОВАНИЕ :Кроме того, вы должны справиться с ситуацией, когда один из потоков не создан (например, уничтожение уже созданных потоков и не создание других), в противном случае другие будут снова застревать в этом бесконечном цикле.

РЕДАКТИРОВАТЬ2

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

Одним из них является то, что в вашем вопросе используется pthread_cond_wait() впоток, который должен ждать инициализации, и pthread_cond_broadcoast() / pthread_cond_signal() в потоке инициализации.

Разница между pthread_cond_signal и pthread_cond_broadcast заключается в следующем: в первом единственный поток получитзаблокировать и выполнить.Остальные все еще должны ждать.При pthread_cond_broadcast все потоки будут разблокированы одновременно.Например:

pthread_mutex_t mtx;
pthread_cond_t  cv;

void* threadFunction(void*);

int main()
{
  pthread_mutex_lock(&mtx);
  for (int i=0; i<5; i++)
  {
    if ((err = pthread_create (&threadID, NULL, threadFunction, NULL))!=0)
    {
       printf("some error\n");
    }
  }
  pthread_cond_broadcast(&cv);
  pthread_mutex_unlock(&mtx);
}

void* threadFunction(void*)
{
  pthread_mutex_lock(&mtx);
  pthread_cond_wait(&cv, &mtx);
  do_things();
  pthread_mutex_unlock(&mtx);
}

Другое решение, на мой взгляд, заключается в использовании блокировки записи и записи: в начале main thread блокирует мьютекс чтения-записи при записи.Другие потоки попытаются заблокировать его (например, в режиме чтения, если вы хотите разбудить их одновременно), но при блокировке записи они будут заблокированы.

Когда все потоки созданы, разблокировка mainа остальные могут выполнить:

pthread_rwlock_t lock; 

void* threadFunction(void*);

int main()
{
  pthread_rwlock_init(&lock, ...);
  //First acquire the write lock:
  if ((res = pthread_rwlock_wrlock(&lock)!=0)
  {
      exit(1);
  } 
  for (int i=0; i<5; i++)
  {
    if ((err = pthread_create (&threadID, NULL, threadFunction, NULL))!=0)
    {
       printf("some error\n");
    }
  }
  pthread_rwlock_unlock(&lock);
  pthread_rwlock_destroy(&lock);
  }

void* threadFunction(void*)
{
  pthread_rwlock_rdlock(&lock);
  do_things();
  pthread_rwlock_unlock(&lock);
}
...