我在我的应用程序中推理了多播套接字线程安全性。首先,我有多个线程共享同一个多播套接字实例,该多播套接字用于连接同一端口上的不同组。以下是我的问题:
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. */
}
我找到了ArrayList
,但它谈到了使用相同的Datagram Packet
。
我也测试了我的应用程序,但我没有发现任何竞争条件或不一致但我不能100%确定使用是线程安全的。
答案 0 :(得分:2)
javadocs没有说明MulticastSocket
是否是线程安全的,但是阅读源代码表明它是。
joinGroup()
和leaveGroup()
方法是native
调用的包装器,它们(反过来)是系统调用的包装器。所有系统调用都是线程安全的,至少就内核空间中保存的数据而言。 (如果不是,那将是一个潜在的安全漏洞。)我对代码的阅读是joinGroup()
和leaveGroup()
不更新任何用户空间数据。
send()
和receive()
方法在DataPacket
个参数上同步,以确保使用相同DataPacket
的两个线程可以安全地执行此操作。除了数据包对象之外,这些方法不会更新用户空间中的任何共享套接字状态,并且(如上所述)我们可以假设内核空间数据是线程安全的。
EJP认为这些系统调用是原子的(按设计),因此是线程安全的。这是正确的 1 。但是,还需要考虑用户空间中的线程安全性(即系统调用之前和之后,或者当两个系统调用共享用户空间缓冲区时)。
1 - 至少我的理解。我找不到一个明确的来源,说明哪些系统调用是原子设计的。
答案 1 :(得分:2)
我是否必须同步调用joinGroup()和leaveGroup()方法?
没有
我是否必须同步调用send()和receive()方法,这些方法总是使用新的数据报包作为参数?
没有
DatagramSocket
读取和写入彼此独立。DatagramSocket
写入在操作系统级别是原子的,因此它们是线程安全的。DatagramSocket
读取由Java同步,它们也是
操作系统级别的原子,所以它们再次是线程安全的。MulticastSocket
从DatagramSocket
继承其I / O方法。joinGroup()/leaveGroup()
在操作系统级也是原子的。为免我被指控plagiarism我将声明该链接本身是我最初几十年前在Sun Java论坛上撰写的未经授权的材料副本。