首页 文章

仅在发送和接收时是否真的需要通过Lock序列化套接字?

提问于
浏览
0

我想知道在使用Pythons套接字时是否真的需要使用例如 threading.Lock ,其中每个线程只从该套接字发送和接收 . 打开和关闭始终由父级处理 .

在搜索答案时,大多数人只是说套接字不是线程安全的,并且需要使用某些东西来序列化它们 . 但没有人真正解释为什么这是必需的 .

其他人说 sendrecv 在操作系统级别上是线程安全的,因此可以并行使用而不进行序列化(here) . 我不知道我在这里是否正确,但我认为Python使用POSIX套接字的C实现,对吗? (套接字的Windows实现怎么样?)

如果不正确调用 sendrecv 没有锁,那为什么呢?是否有可能在线程上接收到另一个请求的数据?

1 回答

  • 2

    只要只有一个发送者或接收者,就没有理由必须将呼叫同步到 sendrecv . 考虑是否有两个线程试图接收消息 . 让我们说,为了便于讨论,client => server消息是8字节长,前4个字节是命令,第二个4字节是某种对象标识符:

    Thread A: sock.recv(8) obtains first 4 bytes
    Thread B: sock.recv(8) obtains second 4 bytes
    

    在这里,两个线程都不会以完整的消息结束 . 现在,很多次都不会发生,你不仅仅是python BTW; C程序也是如此 . )

    所以,是的,套接字是"thread-safe",因为正好一个线程的 recv 将获得给定的数据字节,并且没有什么可以阻止两个线程同时调用 recv . 操作系统在TCP( SOCK_STREAM )套接字中没有任何内容,这将确保一个线程接收到整个"message"(任何长度大于单个字节) .

    如果你有两个线程,一个只接收,一个只发送,那么就没有竞争,也不需要锁定来维护一致的数据流 .

    UDP套接字OTOH是"message-oriented"所以它们没有相同的问题 . 每个 sendrecv 都提供不可分割的数据报 . 接收线程不会获得数据报的一部分 . 它获取整个数据报或没有任何内容(尽管由于缓冲区空间不足,数据报可能会被截断;但在这种情况下,其余部分只是被丢弃而不会被传递到下一个接收线程) .

相关问题