我被分配去解决多线程 java 服务器的一些性能和随机崩溃问题。尽管线程和线程安全对我来说并不是真正的新主题,但我发现设计一个新的多线程应用程序可能比尝试调整一些遗留代码困难一半。我浏览了一些著名的书籍来寻找答案,但奇怪的是,只要我阅读并分析所提供的例子,一切似乎都清晰了。然而,当我第二次查看我应该处理的代码时,我不再确定任何事情!一定是理论知识太多而现实经验太少什么的。
无论如何,回到主题,当我在做一些在线研究时,我遇到了这段代码 https://stackoverflow.com/questions/511552/reading-from-a-socket-not-waiting-for-input。一直困扰我的问题是:在没有同步的情况下从两个单独的线程调用套接字上的 getInputStream() 和 getOutputStream() 真的安全吗?或者我现在对整个线程安全问题有点过于偏执了?猜猜这就是当连续第五本书告诉您并发可能会出现多少问题时会发生的情况。
附言。抱歉,如果问题有点长或者太“菜鸟”,请对我宽容一点——这是我在这里发表的第一篇文章。
Edit:需要明确的是,我知道套接字在全双工模式下工作,并且同时使用它们的输入和输出流是安全的。当您在主线程中获取这些引用然后用它们初始化线程对象时,对我来说似乎很好,但是也安全吗get两个不同线程中的那些流?
@rsp:
所以我检查了Sun的代码并且PlainSocketImpl
正如您所说,确实在这两种方法上同步。Socket
然而,事实并非如此。getInputStream()
and getOutputStream()
几乎只是包装SocketImpl
, so probably并发问题不会导致整个服务器爆炸。尽管如此,由于时机有点不幸,似乎事情could出错(例如,当该方法已经检查错误条件时,其他线程关闭套接字)。
正如您所指出的,从代码结构的角度来看,为每个线程提供流引用而不是整个套接字是一个好主意。如果不是每个线程也使用套接字这一事实,我可能已经重组了我正在处理的代码close()
方法(例如,当套接字收到“shutdown”命令时)。据我所知,这些线程的主要目的是将消息排队以进行发送或处理,因此也许这是违反单一责任原则的,并且这些线程不应该能够关闭套接字(与分离的调制解调器接口 http://www.objectmentor.com/resources/articles/srp.pdf)?但如果我持续分析代码太久,就会发现设计通常存在缺陷,整个事情都需要重写。即使管理层愿意付出代价,认真重构遗留代码、没有任何单元测试以及处理难以调试的并发问题,也可能弊大于利。不是吗?
套接字的输入流和输出流代表两个独立的数据流或通道。在它们之间不同步的线程中使用两个流可以完美保存。套接字流本身将阻止对空或满缓冲区的读取和写入。
Edit:Sun 的套接字实现类,用于同步getInputStream()
and getOutputStream()
方法,然后从不同线程调用应该可以。不过,我同意您的观点,从代码结构的角度来看,将流传递到使用它们的线程可能更有意义(例如,依赖注入有助于测试。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)