13

我有一个设计问题:

我有两个线程,一个心跳/控制线程和一个消息处理线程。

两者都共享同一个套接字,但是 messageHandler 线程只发送消息而从不接收。心跳线程发送和接收(接收消息并对心跳做出反应)。

问题是我不确定这是否安全。我自己没有实现任何机制来查看是否正在使用套接字。那么通过python共享套接字是否自动线程安全?

另外,如果不是,我将它们放在单独的线程中的原因是因为心跳比消息处理更重要。这意味着如果它被消息淹没,它仍然需要做一个心跳。因此,如果我必须实现一个螺栓,是否可以优先考虑我的心跳/控制线程是否需要发送心跳?

4

4 回答 4

20

代替使用第三个线程的更好方法是使用threading.Lock()来保护套接字资源,因为这消除了对第三个线程的需要。与使用第三个线程相比,您的开销和延迟更少。

import threading

lock = threading.Lock()

def sendfunction(sock, data):
    with lock:
        sock.send(data)

您可以从任一线程调用它,但一次只允许一个线程调用sock.send. 当一个线程到达已经被另一个线程锁定的锁时,它将休眠,直到另一个线程释放锁,然后它将获取锁并重复该过程。

threading 模块包含LockRLockCondition,它们在处理多个线程时都非常有用,您会发现非常值得花时间熟悉它们及其用法。

您可以通过在处理每条消息之前检查当前时间与上次发送心跳的时间来将心跳合并到消息处理中,这样可以防止消息泛滥导致无法发送心跳。问题是如果您的消息处理代码没有运行,那么就不会发送心跳。您可以通过让您的消息处理代码每隔一段时间获取一条虚拟消息以允许它检查它是否需要发送心跳并忽略虚拟消息来缓解这种情况。

您应该尽量少用线程(针对单个线程),但是在您的情况下,线程可能没问题,因为它大部分时间都在睡觉。但是,您不应该使用守护线程,因为它们没有正确关闭。尽管在您的情况下可能不存在损坏,但如果它没有正确关闭,它仍然可能会引发某种看起来很糟糕的故障(错误消息)。

我不同意多套接字方法,因为我认为它实际上会使情况复杂化。您会发现许多类型的网络服务/应用程序将心跳和消息合并到单个套接字字节流中。

于 2014-09-27T02:49:47.580 回答
9

不幸的是,多线程共享的套接字不是线程安全的。想想缓冲两个线程在没有锁的情况下操作。

正常的实现方式是使用两个socket,就像ftp一样。cmd socket和msg socket。

如果您想通过一个套接字实现这一点,您可以将不同类型的 msgs 放入不同的队列中,并使用第三个线程消耗队列并通过唯一的套接字发送它们。

这样就可以控制心跳消息优先于数据消息。

于 2012-06-24T11:59:19.627 回答
0

我不知道如何在 Python 级别进行优先级排序。

所以我建议使用 2 个进程,而不是线程,并在操作系统级别进行优先级排序。在 Unix 上,您可以使用 os.nice() 来做到这一点。

你需要使用 2 个套接字,你的共享问题将同时得到解决。

于 2012-06-24T11:28:26.787 回答
0

如果两个线程都是客户端线程,最好打开两个客户端套接字,一个用于检测信号,另一个用于通信。

于 2012-06-24T11:39:15.277 回答