Java套接字多线程安全吗?
Posted
技术标签:
【中文标题】Java套接字多线程安全吗?【英文标题】:Is Java socket multi-thread safe? 【发布时间】:2012-11-12 19:00:56 【问题描述】:如果我有多个 Java 线程同时写入同一个 Socket 实例,这会影响从同一个套接字读取的对象的完整性吗?即对象的内容是否会乱等。对象的顺序可以随机。
【问题讨论】:
它写了什么?数组、数组列表、哈希表?其中之一是线程安全的。 @tuğrul:这是哪一个?使用普通的 ObjectOutputStream(我认为这是他正在做的)并不能提供任何保证。 @Voo:我记得 HashTable 是线程安全的。 ***.com/questions/7400292/… @tuğrul:on 哈希表的操作是线程安全的,并且您可以存储多个哈希表(或其他) 同时在一个流中。后者是流的属性而不是哈希表以及这个问题是关于什么的。 Thread safety of SocketOutputStream的可能重复 【参考方案1】:一般来说,没有任何保证。不同对象的位很可能最终在电线上交错,导致结果难以辨认。 因此,您需要提供外部同步。
有趣的是,即使是操作系统级别的单个套接字写入也不一定是原子的。如需进一步讨论,请参阅Is it safe to issue blocking write() calls on the same TCP socket from multiple threads? 和Be careful with the sendmsg() family of functions。
【讨论】:
那么连接相同两台机器的多个Socket实例呢?如果底层操作系统调用不是线程安全的,那么多个 Socket 实例似乎也不是线程安全的? @JRR:恐怕我不遵循你的推理。在我看来,通过仔细编码,多个套接字可以在没有应用程序级同步的情况下工作。 谢谢。我明白你的意思。我只是问是否没有任何应用程序级同步,多个套接字实例多线程和单个套接字实例多线程是否相同,因为两者都不是线程安全的。 @JRR 这个问题没有意义。如果每个线程都有一个单独的套接字,则根本不会出现线程安全问题。没有任何东西可以被多个线程访问,所以没有什么可以是线程安全的或其他的。 @EJP 好吧,如果多个 Socket 实例共享同一个本机套接字而没有任何锁定机制,那将是一个问题,对吧?【参考方案2】:如果我有多个 Java 线程写入同一个 Socket 实例 同时
您将从多个线程写入相同的OutputStream
。
是什么让您认为没有同步是个好主意?如果您开始同时从多个线程写入文件而不同步,您是否希望该文件包含任何有意义的内容?
【讨论】:
Javadoc from SocketChannel.write() method: "这个方法可以随时被调用。但是,如果另一个线程已经在这个通道上发起了一个写操作,那么这个方法的调用将会阻塞直到第一次手术完成。”所以使用 SocketChannel 进行写入是线程安全的。 是的,SocketChannel 是解决某些人需求的好指针,但我只想指出SocketChannel
属于 NIO 包,它与问题所在的java.net.Socket
是分开的。供参考:***.com/questions/14225957/socket-vs-socketchannel
@Piovezan Socket.
也是如此
@EJP 老实说,我找不到 SocketChannel 实现。我假设它来自操作系统,并且写入同步也取决于操作系统(尽管文档说接受的答案中的第二个链接列出了很多不可信的操作系统)。我确实找到了这个SocketChannelImpl.write(),它具有写锁,但我不确定它们之间的关系。 Socket 的 OutputStream 也来自操作系统,不是吗?
@EJP 实际上我很讨厌通过 GrepCode 进行搜索。 SocketChannelImpl 是每个 SelectorProvider 子类提供的实现。它不是来自操作系统。所以 SocketChannel 具有写锁,但恐怕 Socket 的SocketOutputStream 没有并且依赖于操作系统的(缺乏)原子性。以上是关于Java套接字多线程安全吗?的主要内容,如果未能解决你的问题,请参考以下文章
java priorityblockingqueue 线程安全吗
java 局部静态变量在多线程环境下是不是有线程安全问题??