Есть ли вариант использования для неблокирующего получения, когда у меня есть потоки? - PullRequest
6 голосов
/ 13 апреля 2010

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

Ответы [ 6 ]

4 голосов
/ 23 апреля 2010

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

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

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

2 голосов
/ 29 апреля 2010

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

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

2 голосов
/ 23 апреля 2010

Один поток на соединение часто не очень хорошая идея (неэффективная память, не все ОС очень хороши с большим количеством потоков и т. Д.)

Как прервать блокировку приема вызова? Например, в Linux (и, возможно, в некоторых других ОС POSIX) pthreads + сигналы = катастрофа. С неблокирующим приемом вы можете мультиплексировать ваше ожидание на принимающем сокете и какой-то сокет IPC, используемый для связи между вашими потоками. Также относительно легко сопоставляется с миром Windows.

Если вам необходимо заменить обычный сокет чем-то более сложным (например, OpenSSL), полагаясь на поведение блокировки, вы можете столкнуться с проблемами. Например, OpenSSL может застрять в блокирующем сокете, поскольку протокол SSL имеет сценарии инверсии отправителя / получателя, при которых прием не может быть продолжен до того, как будет выполнена некоторая отправка.

Мой опыт был - «когда сомневаешься использовать неблокирующие розетки».

1 голос
/ 28 апреля 2010

Здесь идет реальная ситуация, с которой я недавно столкнулся. Раньше у меня был скрипт, который запускался каждый час и управлялся crontab, но иногда пользователи заходили на машину и запускали скрипт вручную. У этого были некоторые проблемы, например, одновременное выполнение crontab и пользователем могло вызвать проблемы, и иногда пользователи входили в систему как root - я знаю, что это плохой шаблон, не под моим контролем - и запускали скрипт с неправильными разрешениями. Поэтому мы решили запустить подпрограмму как демон с соответствующими разрешениями, и команда, которую использовали пользователи для запуска, теперь просто запускает демон.

Таким образом, эта команда, выполняемая пользователем, в основном делает две вещи: запускает демон и ждет, пока он завершит задачу. Но для этого также потребовалось время ожидания, чтобы пользователь мог дампить логи демонов во время ожидания.

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

К счастью для меня, я не думал об использовании потоков. Вероятно, я бы так и думал, если бы писал код на Java, но это был код Python.

1 голос
/ 23 апреля 2010

Я не могу думать ни о каком другом, но иногда неблокирующие API-интерфейсы разрабатываются таким образом, чтобы их было проще / интуитивно понятнее использовать, чем явно многопоточная реализация.

0 голосов
/ 23 апреля 2010

Суть в том, что когда мы считаем потоки и обмен сообщениями идеальными, реальный компромисс заключается в написании планировщика для планирования неблокирующих операций приема и написании кода синхронизации для потоков с общим состоянием (блокировки и т. Д.). Я бы сказал, что и то, и другое может быть иногда легким, а иногда и трудным. Таким образом, случай использования будет, когда есть много сообщений асинхронных сообщений, которые будут получены, и когда есть много данных для обработки на основе сообщений. Это было бы довольно просто в одном потоке, использующем неблокирующее получение, и потребовало бы большой синхронизации со многими потоками и общим состоянием .... Я также думаю о некотором реальном примере, я включу его, вероятно, позже.

...