java.net.Socket 线程安全的方式是什么?
我有一个可以通过 BufferedReaders 和 BufferedWriters 读取和写入的 Socket。我不确定可以从单独的线程执行哪些操作。我猜想同时从两个不同的线程写入套接字是一个坏主意。与同时从两个不同线程读取套接字相同。在一个线程上读取而在另一个线程上写入怎么样?
我之所以这么问,是因为我想让一个线程在读取时长时间阻塞,因为它等待更多数据,但在等待期间,我偶尔也会有数据要在套接字上发送。我不清楚这是否是线程安全的,或者我是否应该在写入之前取消读取(这会很烦人)。
I have a Socket that I am both reading and writing to, via BufferedReaders and BufferedWriters. I'm not sure which operations are okay to do from separate threads. I would guess that writing to the socket from two different threads at the same time is a bad idea. Same with reading off the socket from two different threads at the same time. What about reading on one thread while writing on another?
I ask because I want to have one thread blocked for a long time on a read as it waits for more data, but during this wait I also have occasional data to send on the socket. I'm not clear if this is threadsafe, or if I should cancel the read before I write (which would be annoying).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
套接字在流级别是线程不安全的。您必须提供同步。唯一的保证是,无论并发性如何,您都不会在不同的读取调用中获得完全相同字节的副本。
但在读者级别,特别是作家级别,您可能有一些 锁定问题。
无论如何,您可以使用 Socket 的流处理读写操作,就好像它们是完全独立的对象一样(它们是,它们唯一共享的是它们的生命周期)。
一旦您一方面在读取器线程和另一方面写入器线程之间提供了正确的同步,则任意数量的读取器和写入器都可以。这意味着,是的,您可以在一个线程上读取并在另一个线程上写入(事实上,这是非常频繁的),并且您不必在写入时停止读取。
最后一个建议:所有涉及线程的操作都有关联的超时,请确保正确处理超时。
Sockets are thread unsafe at the stream level. You have to provide synchronization. The only warranty is that you won't get copies of the exact same bytes in different read invocations no matter concurrency.
But at a Reader and, specially, Writer level, you might have some locking problems.
Anyway, you can handle read and write operations with the Socket's streams as if they were completely independent objects (they are, the only thing they share is their lifecyle).
Once you have provided correct synchronization among reader threads on one hand, and writer threads on the other hand, any number of readers and writers will be okay. This means that, yes, you can read on one thread and write on another (in fact that's very frequent), and you don't have to stop reading while writing.
One last advice: all of the operations involving threads have associated timeout, make sure that you handle the timeouts correctly.
实际上,您从 InputStream 读取数据并将其写入 OutputStream。它们是相当独立的,只要您序列化对它们中的每一个的访问就可以了。
但是,您必须将发送的数据与接收的数据关联起来。这与线程安全不同。
You actually read from InputStream and write to OutputStream. They are fairly independent and for as long as you serialize access to each of them you are ok.
You have to correlate, however, the data that you send with data that you receive. That's different from thread safety.
Java
java.net.Socket
实际上并不是线程安全的:打开 Socket 源代码,查看(比方说)connected
成员字段及其使用方式。您将看到它不是易失性
,无需同步即可读取和更新。这表明 Socket 类并不是设计用于多线程使用的。虽然那里有一些锁和同步,但它并不一致。`我建议不要这样做。最终,使用缓冲区(nio),并在一个线程中进行套接字读/写
有关详细信息,请参阅讨论v
Java
java.net.Socket
is not actually thread safe: Open the Socket source, and look at the (let say)connected
member field and how it is used. You will see that is notvolatile
, read and updated without synchrinization. This indicates that Socket class is not designed to be used by multiple threads. Though, there is some locks and synchronization there, it is not consistent.`I recommend not to do it. Eventually, use buffers(nio), and do socket reads/writes in one thread
For details go the the discussionv
您可以让一个线程读取套接字,而另一个线程写入它。您可能希望有多个线程写入套接字,在这种情况下,您必须通过同步序列化您的访问,或者您可以有一个写入线程从队列中获取要写入的数据。 (我更喜欢前者)
可以使用非阻塞IO并在单个线程中共享读写工作。然而,这实际上更复杂且更棘手。如果你想这样做,我建议你使用一个库来帮助你,比如 Netty 或 Mina。
You can have one thread reading the socket and another thread writing to it. You may want to have a number of threads write to the socket, in which case you have to serialize your access with synchronization or you could have a single writing thread which gets the data to write from a queue. (I prefer the former)
You can use non-blocking IO and share the reading and writing work in a single thread. However this is actually more complex and tricky to get right. If you want to do this I suggest you use a library to help you such as Netty or Mina.
非常有趣,nio SocketChannel 写入是同步的
http:// www.docjar.com/html/api/sun/nio/ch/SocketChannelImpl.java.html
旧的 io Socket 内容取决于操作系统,因此您必须查看操作系统本机代码才能了解当然(这可能因操作系统而异)...
只需查看 java.net.SocketOutputStream.java,它就是 Socket.getOutputStream 返回的内容。
(当然,除非我错过了什么)。
哦,还有一件事,他们可以在每个操作系统上的每个 JVM 的本机代码中进行同步,但谁知道呢。只有nio明显知道同步的存在。
Very interesting, the nio SocketChannel writes are synchronized
http://www.docjar.com/html/api/sun/nio/ch/SocketChannelImpl.java.html
The old io Socket stuff depends on the OS so you would have to look at the OS native code to know for sure(and that may vary from OS to OS)...
Just look at java.net.SocketOutputStream.java which is what Socket.getOutputStream returns.
(unless of course I missed something).
oh, one more thing, they could have put synchronization in the native code in every JVM on each OS but who knows for sure. Only the nio is obvious that synchronization exists.
这就是本机代码中的 socketWrite 的方式,因此从代码来看它不是线程安全的
This is how socketWrite in native code, so it's not thread safe from the code