Ожидание завершения pthread_create без использования pthread_join - PullRequest
1 голос
/ 08 апреля 2009

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

В теме 1:

lock_OfflineWorker.Lock()
if (pthread_create(&tid0, NULL, RunOfflineWorker, NULL) != 0)
{
}

lock_OfflineWorker.TryLock();
lock_OfflineWorker.Unlock();

В теме 2:

bool OfflineWorker::Initialize()
{
  lock_OfflineWorker.Unlock();
}

Но это не элегантно, и я не слишком уверен в побочных эффектах (возможен еще один тупик). Это нормально? Если нет, есть ли другой способ добиться этого (используя блокировки или иным образом)

РЕДАКТИРОВАТЬ: Забыли включить функцию «RunOfflineWorker»

void* RunOfflineWorker(void* pData)
{   
  g_OfflineWorker.Initialize();
}

Ответы [ 2 ]

7 голосов
/ 08 апреля 2009

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

Thread1 ожидает с pthread_cond_wait(), а thread2 сообщает об этом с pthread_cond_signal().

Вам нужно:

bool            condition ; // or anything else to be tested
pthread_mutex_t mutex ;
pthread_cond_t  cond ;

Первый поток объединяет все:

condition = false ;
pthread_mutex_init( &mutex , PTHREAD_MUTEX_INITIALIZER );
pthread_cond_init( &cond , PTHREAD_COND_INITIALIZER );

Затем он ждет с заблокированным мьютексом. Обычно вы помещаете ожидание в цикл, чтобы проверить состояние, какое бы оно ни было.

pthread_mutex_lock( &mutex );
while( ! condition )
{
    pthread_cond_wait( &cond , &mutex );
}
pthread_mutex_unlock( &mutex );

Другой поток делает это при необходимости:

pthread_mutex_lock( &mutex );
condition = true ; // or false ...
pthread_cond_signal( &cond );
pthread_mutex_unlock( &mutex );
1 голос
/ 08 апреля 2009

Я думаю, что ваше решение просто отлично, за исключением того, что вам нужно использовать lock_OfflineWorker.Lock() вместо lock_OfflineWorker.TryLock() в потоке 1 - с TryLock(), оно на самом деле ничего не ждет. Вы не можете использовать мьютекс для этого, потому что он должен быть освобожден тем же потоком, который его заблокировал, но, например,. блокировка на основе семафора будет делать. Использование монитора (т. Е. Mutex + condvar) было бы более сложным.

О взаимоблокировках: взаимоблокировки невозможны, если часть инициализации OfflineWorker (т. Е. Код перед снятием блокировки) нигде не ждет. Если в вашем решении есть реальные взаимоблокировки, любое другое решение, которое заставляет поток 1 ожидать поток 2, тоже будет иметь их (я могу представить себе такую ​​ситуацию).

Редактировать после комментария: если вы передаете сообщения потоку 1, пока он ожидает завершения инициализации потока 2, у вас есть возможность тупиковой блокировки, особенно если есть некоторый ограниченный буфер для сообщений или если функция передачи сообщений ожидает для ответа. В этой ситуации я бы предложил просто отказаться от идеи ожидания потока 2 и, возможно, передать некоторый обратный вызов, который будет вызван из потока 2 после завершения инициализации.

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