Многопоточный спиновый замок? - PullRequest
3 голосов
/ 26 мая 2011

Мой демон инициализирует себя в четырех разных потоках, прежде чем он начинает делать свои вещи.Прямо сейчас я использую счетчик, который увеличивается, когда поток запускается, и уменьшается, когда он заканчивается.Когда счетчик достигает 0, я вызываю обратный вызов инициализации.

Это предпочтительный способ сделать это, или есть лучшие способы? Я использую потоки POSIX (pthread)и я просто запускаю цикл while, чтобы дождаться, пока счетчик не достигнет 0.

Редактировать: pthread_barrier_* функции недоступны на моей платформе, хотя они кажутся лучшимивыбор.

Редактировать 2: Не все потоки выходят.Некоторые инициализируют, а затем прослушивают события.По сути, поток должен сказать: «Я закончил инициализацию».

Ответы [ 6 ]

7 голосов
/ 26 мая 2011

Барьер - это то, что вам нужно. Они были созданы для того, чтобы перед тем, как продолжить, нужно «встретиться» в определенные моменты. Смотрите pthread_barrier _ *

3 голосов
/ 26 мая 2011

Вместо вращения используйте примитивы pthread mutex / condvar.Я бы предложил один мьютекс для защиты как количества ожидающих потоков, так и condvar.

Основной цикл выглядит так:

acquire mutex
count=N_THREADS;
start your N threads
while (1) {
  if (count==0) break;
  cond_wait(condvar);
}
release mutex

И когда каждый поток готов, он будетсделайте что-то вроде этого:

acquire mutex
count--
cond_signal(condvar)
release mutex

(РЕДАКТИРОВАТЬ: я предположил, что потоки должны продолжать работать после того, как они выполнили свою инициализацию. Если они должны закончить, используйте pthread_join, как сказали другие.) * +1010 *

3 голосов
/ 26 мая 2011

Звучит ... странно.Разве вы не должны просто использовать pthread_join () для ожидания завершения потоков?Может быть, я не понимаю вопроса.

3 голосов
/ 26 мая 2011

pthread_join - предпочтительный способ ожидания pthreads.

0 голосов
/ 26 мая 2011

Итак, что произойдет, если один поток завершит инициализацию до того, как начнется какой-либо другой?

Итак, один из способов сделать это

  1. инициализировать атомный счетчик равным 0
  2. когда каждый поток завершается с помощью init, увеличить счетчик и получить значение атомарно.Если вы используете GCC, вы можете использовать __sync_add_and_fetch ()
  3. Если полученное значение счетчика
  4. Если полученное значение счетчика == N_threads, фаза инициализации завершена, сигнализировать о состоянии и продолжить.
0 голосов
/ 26 мая 2011

Как отметил Клас Линдбек в своем ответе, присоединение к темам является предпочтительным способом. Если ваши потоки не завершаются (то есть являются частью пула многократного использования и т. Д.), Логика звучит хорошо. Единственное, что использование счетчика без какой-либо синхронизации опасно. Вы должны использовать мьютекс с условием или атомное целое число. Я бы рекомендовал использовать условие mutex +, если вы не хотите вращаться на атомном счетчике в потоке, который ожидает завершения инициализации.

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