MulticastSocket join/leave group, send, receive thread-safety

MulticastSocket join/leave group, send, receive thread-safety

我在推理我的应用程序中的多播套接字线程安全性。首先,我有多个线程共享同一个多播套接字实例,这个多播套接字用于在同一端口上加入不同的组。这是我的问题:

  1. 我是否必须同步对 joinGroup()leaveGroup() 方法的调用?
  2. 我是否必须同步对 send()receive() 方法的调用,这些方法始终使用数据报包的新实例作为参数?

这是第二个问题的代码示例:

/* SEND METHOD EXAMPLE. */
    DatagramPacket sndPckt = new DatagramPacket(buf, buf.length, groupAddr,port);
    try{
        multicastSocket.send(sndPckt);
    } catch (IOException e) {
        /* Error handling. */
    }
/* RECEIVE METHOD EXAMPLE. */
    DatagramPacket recv = new DatagramPacket(buf, buf.length);
        try{
            multicastSocket.receive(recv);
        } catch (IOException e) {
            /* Error handling. */
        }

我找到了 this answer,但它谈到使用相同的Datagram Packet。 我也测试了我的应用程序,但我没有发现任何竞争条件或不一致,但我不能 100% 确定使用是线程安全的。

javadocs 没有说明 MulticastSocket 是否是线程安全的,但阅读源代码表明它是。

  1. joinGroup()leaveGroup() 方法是 native 调用的包装器,它们(反过来)是系统调用的包装器。所有系统调用都是线程安全的,至少就内核-space 中保存的数据而言是这样。 (如果不是,那将是一个潜在的安全漏洞。)我对代码的解读是 joinGroup()leaveGroup() 不更新任何用户-space 数据。

  2. send()receive() 方法在它们的 DataPacket 参数上同步,以确保使用相同 DataPacket 的两个线程可以安全地这样做。除了数据包对象之外,这些方法不会更新 user-space 中的任何共享套接字状态,并且(如上所述)我们可以假设 kernel-space 数据是线程安全的。

EJP 认为这些系统调用是原子的(按设计),因此是线程安全的。那是正确的1。但是,还需要考虑 user-space 中的线程安全(即系统调用之前和之后,或者当两个系统调用共享一个 user-space 缓冲区时)。


1 - 至少在我看来是这样。我找不到明确的来源说明哪些系统调用在设计上是原子的。

Do I have to synchronize calls to joinGroup() and leaveGroup() methods?

没有

Do I have to synchronize calls to send() and receive() methods which uses always new istance of datagram packet as parameter?

没有

  • DatagramSocket读写相互独立
  • DatagramSocket 写入在 OS 级别是原子的,因此它们是线程安全的。
  • DatagramSocket 读取由 Java 同步,它们也是 OS 级别的原子,因此它们也是线程安全的。
  • MulticastSocketDatagramSocket.
  • 继承其 I/O 方法
  • joinGroup()/leaveGroup() 在 OS 级别也是原子的。

以免我被指责 plagiarism 我会声明 link 本身是 material 的未经授权的副本 我最初在 Sun Java 论坛上写了几十年前.