#python #multithreading #sockets #locking
#python #многопоточность #сокеты #блокировка
Вопрос:
У меня есть несколько устройств, с которых мне нужно получать обновления статуса. Объект socket — это все, что у меня есть, а socket.recv() — это все, что мне нужно для получения статуса. При установке в однопоточное приложение проблем не возникает:
class Device:
def receive(self):
log.debug("receive waiting: %r", self.device_id)
try:
packet = self.socket.recv(255)
except Exception as e:
self.report_socket_error(e)
self.reconnect()
log.debug("received response: %r", self.device_id)
d = Device()
d.connect()
while True:
d.receive()
Однако тот же код, завернутый в многопоточность.Класс Thread вызывает взаимоблокировки и странное поведение. Обертывание его блокировками ничего не изменило. Я проследил проблему вплоть до socket.recv() call…So как реализовать несколько потоков, где каждый поток владеет одним сокетом (1 поток владеет исключительно 1 сокетом), которые могут ожидать данных одновременно?
Заранее спасибо
Комментарии:
1. Почему вы устанавливаете блокировку? Вы используете какой-либо ресурс? отправка / recv в соответствии с POSIX являются атомарными операциями. Возможно, вы недостаточно хорошо использовали потоковую обработку. Можете ли вы поделиться кодом, в котором вы реализовали потоки?
Ответ №1:
Я знаю, что это не отвечает на ваш вопрос о том, как решить вашу проблему взаимоблокировки, однако, похоже, что использование потоков в вашем случае является накладным:
Вы можете просто использовать один поток, в котором вы используете select()
, чтобы выяснить, в каком сокете есть доступные данные, а затем обработать сообщенные данные. Если обработка не занимает много времени или ваш протокол не сложнее select
, все должно быть в порядке и избегать всех проблем с потоками.
Взгляните на http://docs.python.org/howto/sockets.html#non-blocking-sockets для получения дополнительной информации.
Ответ №2:
Из скольких разных сокетов вам нужно читать?
- Если ответ «только один», то используйте только один поток. Добавление другого никак вам не поможет, а только усложнит вашу жизнь, как вы выяснили.
-
Если ответ «несколько», то один из способов организовать это — действительно иметь поток на сокет.
recv
это блокирующая операция, которая делает поток привлекательным вариантом для организации кода. Каждый поток владеет отдельным сокетом и читает из него на досуге. У вас не должно возникнуть проблем и взаимоблокировок с этим.Блокировки не нужны, пока ресурсы не являются общими. Даже если вы совместно используете ресурсы (ведение журнала, некоторое хранилище данных и т.д.), Не используйте просто простые блокировки — в Python для этого есть утилиты более высокого уровня, такие как
Queue
module.