Есть ли способ узнать, заблокирован ли поток?

Я пишу класс пула потоков в C ++, который получает задачи для параллельного выполнения. Я хочу, чтобы все ядра были заняты, если это возможно, но иногда некоторые потоки бездействуют, потому что они заблокированы на время для целей синхронизации. Когда это происходит, я хотел бы начать новый поток, чтобы всегда было примерно столько же бодрствующих потоков, сколько ядер ЦП. Для этого мне нужен способ выяснить, находится ли определенный поток в активном состоянии или находится в режиме ожидания (заблокирован). Как я могу это выяснить?

Я бы предпочел использовать стандартную библиотеку C ++ 11 или boost для переносимости. Но при необходимости я бы также использовал WinAPI. Я использую Visual Studio 2012 на Windows 7. Но на самом деле я хотел бы иметь портативный способ сделать это.

Предпочтительно этот пул потоков должен уметь обрабатывать такие случаи, как

MyThreadPool pool;
for ( int i = 0; i < 100; ++i )
pool.addTask( &block_until_this_function_has_been_called_a_hundred_times );
pool.join(); // waits until all tasks have been dispatched.

где функция block_until_this_function_has_been_called_a_hundred_times() блоки до 100 потоков вызвали его. В это время все потоки должны продолжать работать. Одним из требований к пулу потоков является то, что он не должен блокироваться из-за слишком малого числа потоков в пуле.

5

Решение

использование Boost Asio. Он имеет собственную структуру управления пулами потоков и планирования. Основная идея состоит в том, чтобы подтолкнуть задачи к io_service объект с помощью post() метод и вызов run() из столько потоков, сколько у вас процессорных ядер. Вы должны создать work объект во время выполнения расчета, чтобы избежать выхода из потоков, если у них недостаточно рабочих мест.

Важная вещь в Asio — никогда не использовать блокирующие вызовы. Для вызовов ввода / вывода используйте асинхронные вызовы собственных объектов ввода / вывода Asio. Для синхронизации используйте strand объекты вместо мьютексов. Если вы отправляете функции в службу io, которая обернута в цепочку, то это гарантирует, что в любое время выполняется не более одной задачи, принадлежащей определенной цепочке. В случае конфликта задача остается в очереди событий Asio, а не блокирует рабочий поток.

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

2

Другие решения

Добавьте средство в свой пул потоков, чтобы поток мог сказать «Я заблокирован», а затем «Я больше не заблокирован». Перед каждым значительным блокирующим действием (см. Ниже то, что я имею в виду), подайте сигнал «Я заблокирован», а затем «Я больше не заблокирован».

Что представляет собой «значительное блокирующее действие»? Конечно, это не простая блокировка мьютекса: мьютексы должны удерживаться только в течение короткого периода времени, поэтому блокировка мьютекса не имеет большого значения. Я имею в виду такие вещи, как:

  • Ожидание завершения ввода-вывода
  • Ожидание завершения другой задачи пула
  • Ожидание данных в общей очереди

и другие подобные события.

3

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector