我遇到了设计问题:
我有两个线程,一个心跳/控制线程和一个消息处理程序线程。
两者都共享同一个套接字,但是messageHandler线程只发送消息而从不接收。心跳线程发送和接收(接收消息并对心跳作出反应)。
问题是我不确定这是否安全。我自己没有实现查看套接字是否正在使用的机制。 那么在python上自动共享套接字是否自动线程安全?
此外,如果不是,我将它们放在一个单独的线程中的原因是因为心跳比消息处理更重要。这意味着如果它充满了消息,它仍然需要做一个心跳。所以,如果我必须实现一个螺栓,那么如果我的心跳/控制线程需要发送心跳,我可以优先考虑吗?
答案 0 :(得分:12)
更好的方法是使用threading.Lock()
来保护套接字资源,而不是使用第三个线程,因为这样就不需要第三个线程了。与第三个线程相比,您的开销更低,延迟更少。
import threading
lock = threading.Lock()
def sendfunction(sock, data):
with lock:
sock.send(data)
您可以从任一线程调用它,但一次只允许一个线程调用sock.send
。当一个线程到达已经被另一个线程锁定的锁时,它将一直处于休眠状态,直到另一个线程释放锁,然后它将获得锁并重复该过程。
线程模块包含Lock
,RLock
和Condition
,它们在处理多个线程时都非常有用,您会发现值得花些时间熟悉它们与他们及其用法。
您可以通过在处理每条消息之前检查上次发送心跳的当前时间,将心跳合并到您的消息处理中,这样可以防止被消息淹没导致心跳不被发送。问题是如果您的消息处理代码没有运行,那么将不会发送心跳。你可以通过让你的消息处理代码在间隔上获得一个虚拟消息来缓解这个问题,以便它能够检查它是否需要发送心跳并忽略虚拟消息。
你应该尝试谨慎使用线程(针对单个线程)但是在你的情况下,一个线程可能没问题,因为它将花费大部分时间睡觉。但是,您应该不使用守护程序线程,因为它们没有正确关闭。虽然如果没有正确关闭,在您的情况下可能不存在损坏,但仍然可能会抛出某种类型的错误(错误消息),这看起来很糟糕。
我不同意多套接字方法,因为我认为它实际上会使情况复杂化。您会发现许多类型的网络服务/应用程序将心跳和消息合并到单个套接字字节流中。
答案 1 :(得分:5)
不幸的是,多线程共享的套接字不是线程安全的。关于缓冲区两个线程的操作,没有锁定。
实现的正常方法是使用两个套接字,就像ftp does.cmd套接字和msg套接字一样。
如果你想通过一个套接字实现它,你可以将不同类型的msgs放入不同的队列,第三个线程使用队列并通过唯一的套接字发送它们。
通过这种方式,您可以将心跳msg priory控制为数据消息。
答案 2 :(得分:0)
我不知道如何在Python级别优先处理。
所以我建议使用2个进程,而不是线程,并在操作系统级别优先。在Unix上,你可以使用os.nice()来做到这一点。
然后你需要使用2个套接字,你的共享问题将同时得到解决。
答案 3 :(得分:0)
如果两个线程都是客户端线程,最好打开两个客户端套接字,一个到服务器进行心跳,另一个进行通信。