MulticastSocket join/leave group, send, receive thread-safety
MulticastSocket join/leave group, send, receive thread-safety
我在推理我的应用程序中的多播套接字线程安全性。首先,我有多个线程共享同一个多播套接字实例,这个多播套接字用于在同一端口上加入不同的组。这是我的问题:
- 我是否必须同步对
joinGroup()
和 leaveGroup()
方法的调用?
- 我是否必须同步对
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
是否是线程安全的,但阅读源代码表明它是。
joinGroup()
和 leaveGroup()
方法是 native
调用的包装器,它们(反过来)是系统调用的包装器。所有系统调用都是线程安全的,至少就内核-space 中保存的数据而言是这样。 (如果不是,那将是一个潜在的安全漏洞。)我对代码的解读是 joinGroup()
和 leaveGroup()
不更新任何用户-space 数据。
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 级别的原子,因此它们也是线程安全的。
MulticastSocket
从 DatagramSocket
. 继承其 I/O 方法
joinGroup()/leaveGroup()
在 OS 级别也是原子的。
以免我被指责 plagiarism 我会声明 link 本身是 material 的未经授权的副本 我最初在 Sun Java 论坛上写了几十年前.
我在推理我的应用程序中的多播套接字线程安全性。首先,我有多个线程共享同一个多播套接字实例,这个多播套接字用于在同一端口上加入不同的组。这是我的问题:
- 我是否必须同步对
joinGroup()
和leaveGroup()
方法的调用? - 我是否必须同步对
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
是否是线程安全的,但阅读源代码表明它是。
joinGroup()
和leaveGroup()
方法是native
调用的包装器,它们(反过来)是系统调用的包装器。所有系统调用都是线程安全的,至少就内核-space 中保存的数据而言是这样。 (如果不是,那将是一个潜在的安全漏洞。)我对代码的解读是joinGroup()
和leaveGroup()
不更新任何用户-space 数据。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 级别的原子,因此它们也是线程安全的。MulticastSocket
从DatagramSocket
. 继承其 I/O 方法
joinGroup()/leaveGroup()
在 OS 级别也是原子的。
以免我被指责 plagiarism 我会声明 link 本身是 material 的未经授权的副本 我最初在 Sun Java 论坛上写了几十年前.