Реализация пула потоков - PullRequest
1 голос
/ 30 марта 2011

Я хотел бы создать простой пул потоков (в системе * nix) для обработки ввода на моем асинхронном коммуникационном сервере. И у меня есть несколько вопросов. Сначала я просто хочу иметь статическое число потоков, произвольно сказать 6.

Как отправить команду в рабочий поток?

Я думал об использовании простой связи через сокет с чем-то вроде этого

основной поток :: send [(recv) socket (send) otherSocket];

тогда мои потоки просто блокируются при получении вызова, это ужасно неэффективно?

Есть ли библиотека, которую я должен использовать? Есть ли лучшие методы реализации?

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

Ответы [ 3 ]

3 голосов
/ 30 марта 2011

Прежде всего, вы должны понимать, что в Windows встроен не один, а два API пула потоков. В случае, если этого недостаточно, порты завершения ввода-вывода также являются в основном пулами потоков. маскировка. Таким образом, , вероятно, не так уж много причин для написания собственного пула потоков.

Если вы не планируете запускать потоки на разных компьютерах, я бы не использовал сокеты для связи. Обычное намерение с потоками состоит в том, чтобы они сводили накладные расходы к минимуму; сокеты не очень хорошо подходят для этого. Если вы пересекаете границы компьютера, гораздо больше накладных расходов (сетевое взаимодействие) становится почти неизбежным, и в этом случае использование сокетов вместо какого-либо другого сетевого API не имеет большого значения. Также обратите внимание, что для работы на нескольких машинах вам нужно сделать немного больше в общем, сортировать данные из одного в другой и т. Д.

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

2 голосов
/ 30 марта 2011

Поскольку вы используете сокеты, вам придется использовать что-то вроде select или poll для ожидания активности сокетов.Поэтому для связи между потоками (itc) что-то, что использует дескриптор файла, будет очень полезно.Это может быть пара или каналы или сокет домена unix.

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

Если вы подключаетесь и ждете на бэкэнд-сервере (например, базе данных), вы можете решить заблокировать, ожидая завершения recv, хотя вам, вероятно, следует избегать этого.Ваш сервер будет более отзывчивым, если вы используете конечный автомат и свернете свой стек обратно к выбранному виду (после добавления дескриптора бэкэнд-файла в цикл выбора / опроса).Это облегчит вашему основному потоку управление вашим рабочим потоком.Если вы сообразительны, ваши потоки могут обрабатывать более одного запроса за раз, и только с несколькими потоками у вас должен быть очень масштабируемый сервер.

Старайтесь не использовать семафор или мьютексы для itc, а отправляйте все запросы через каналы itc или доменные сокеты unix.Вы избавите себя от сильной боли в гоночных условиях.

2 голосов
/ 30 марта 2011

Есть ли библиотека, которую вы должны использовать? Ну, конечно, иначе вы не сможете выполнить то, что хотите в стандартном C ++. Это ставит под вопрос, какую платформу вы хотите использовать ... используете ли вы Windows или какой-то вариант Linux? Если вы используете Windows, вы можете использовать потоки Windows и Win Socks 2. Если вы используете Linux, вы можете попробовать использовать многопоточность Posix, а что касается сети, я не совсем уверен. Тем не менее, вы можете просто использовать библиотеки Boost для всего этого, и это должно работать в Windows и вашей ОС Linux.

Что касается отправки сообщения, вы можете использовать мьютекс для своей очереди сообщений и просто иметь функцию получения сообщений, которая блокирует ее и добавляет сообщение, которое работает как для входящих сетевых сообщений из сокета в любом потоке, и для других потоков, желающих отправить сообщение в этот поток. Также не забывайте, что когда поток обрабатывает сообщения, вы также хотите заблокировать мьютекс; каждый раз, когда вы обращаетесь к этой очереди сообщений, она должна быть заблокирована, чтобы предотвратить коллизию / ошибки данных.

...