【问题标题】:How to implement threaded socket.recv() in python?如何在python中实现线程socket.recv()?
【发布时间】:2011-04-23 13:51:39
【问题描述】:

我有许多设备需要从中获取状态更新。我只有一个套接字对象,而我只需要 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()

但是,包装在 threading.Thread 类中的相同代码会导致死锁和有趣的行为。用锁包裹它并没有改变任何东西。我将问题追溯到socket.recv()调用......那么,如何实现多个线程,每个线程拥有一个套接字(1个线程独占1个套接字),它们能够同时等待数据?

提前致谢

【问题讨论】:

  • 你为什么要锁?您是否共享任何资源?根据 POSIX,发送/接收是原子操作。可能是你没有很好地使用线程。你能分享你实现线程的代码吗?

标签: python multithreading sockets locking


【解决方案1】:

我知道这并不能回答您关于如何解决死锁问题的问题,但是在您的情况下,它似乎是因为您使用线程是开销:

您可以只使用一个使用select() 的线程来找出哪个套接字有可用数据,然后处理报告的数据。除非处理需要很长时间或者您的协议更复杂,否则select 应该没问题并避免所有线程问题。

查看http://docs.python.org/howto/sockets.html#non-blocking-sockets了解更多详情。

【讨论】:

    【解决方案2】:

    您必须读取多少个不同的套接字?

    • 如果答案是“只有一个”,那么只使用一个线程。正如您发现的那样,添加另一个对您没有任何帮助,只会使您的生活复杂化。
    • 如果答案是“几个”,那么组织它的一种方法确实是每个套接字都有一个线程。 recv 是一种阻塞操作,它使线程成为组织代码的有吸引力的选择。每个线程拥有一个单独的套接字并在空闲时从它读取。你应该没有问题和僵局。

      只要不共享资源,就不需要锁。即使您确实共享资源(日志记录、一些数据存储等),也不要只使用简单的锁 - Python 具有更高级别的实用程序,例如 Queue 模块。

    【讨论】:

      猜你喜欢
      • 2011-02-24
      • 2017-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多