2012-07-02 5 views
1

Я пишу многопоточную программу на C++, используя библиотеку потоков C++ 11.Управление несколькими параллельными потоками

У меня есть следующие требования:

  1. Основной поток прослушивает к некоторому типу событий, и выстреливает новый поток для каждого нового события
  2. Когда завершение программы запрашиваются, новое творение потока блокируется и мы ждем завершения старых потоков

У меня есть возможность хранить потоки в некотором контейнере, например, список. Перед выходом все нити в контейнере: join() -ed. Однако, поскольку контейнеры STL не являются потокобезопасными, необходима дополнительная синхронизация при добавлении нового потока и удалении готового потока из контейнера. В этом случае взаимодействие между основным потоком и дочерними потоками становится немного сложнее. Должна ли дочерняя нить удаляться из контейнера? Если нет, то как он может сообщить основному потоку, когда пришло время удалить? и т. д.

Еще один способ, по которому я вижу, состоит в том, чтобы иметь атомный int, который увеличивается при помощи основного потока при создании дочернего потока и декрементируется дочерним потоком прямо перед его завершением (потоки будут detach() -ed после создания, поэтому мне не придется управлять любыми объектами std :: thread). Перед выходом, мы просто ожидаем, что атомное целое число станет 0 в простой петле. Это решение выглядит лучше для меня, потому что есть меньше движущихся частей и нет блокировки (по крайней мере, до тех пор, пока целевая платформа имеет незафиксированную реализацию std::atomic<int>).

Итак, мой вопрос в том, какой из вышеперечисленных методов вы предпочитаете?

+0

Вам нужна новая тема для каждого мероприятия? Если у вас много, и особенно если они короткие, создание/уничтожение потоков будет огромным накладным. В зависимости от вашей ситуации вы можете реализовать какой-то пул потоков с фиксированным количеством рабочих потоков. Просто предложение –

+1

Если основной поток уже прослушивает события, почему дочерние потоки не могут отправлять основной поток, сигнализируя о завершении события? Тогда только основной поток когда-либо коснется контейнера, и синхронизация не требуется. – ildjarn

+0

@ АлександрКондрацкий Я знаю, но это был осознанный выбор. У меня мало что происходит, и дочерние потоки могут занять значительное время, поэтому я не вижу необходимости использовать пул потоков. –

ответ

1

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

// the waiter 
{ 
    std::lock_guard<std::mutex> g(threads_lock); 
    while (threads > 0) { 
     threads_cond.wait(threads_lock); 
    } 
} 
//... 

// the threads that are exiting 
if (--threads == 0) { 
    std::lock_guard<std::mutex> g(threads_lock); 
    threads_cond.notify_one(); 
} 

Это предполагает, что threads является std::atomic, конечно.

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