我知道问题的答案可能很明显。但如果有人能给我一个明确的答案,那将会有所帮助。
问题是:java NIO包是否可以提供一些内存一致性保证?
场景是:
Thread A Thread B
[modify Object X]
[Send a request A over TCP by NIO]
[receive response for request A over TCP by NIO]
[read Object X]
如果应用程序在线程A和线程B之间没有任何同步/安全引用脉冲,则线程A对线程A进行的修改是否可见。
非常感谢你的帮助。
答案 0 :(得分:5)
我的猜测是TCP请求不对线程同步做出任何正式保证。
那就是说,我认为你提出的问题有一个简单的解决方案:假设TCP请求至少与获取锁定一样昂贵(按性价比)是合理的。因此,您可以将发送/接收封装在同步块中,而不会显着降低性能。这将确保线程B在修改后看到对象X.
答案 1 :(得分:5)
JMM 明确对此方案不作任何保证。除非两个线程在同一个对象上同步 ,否则两个线程之间没有“事先发生”保证。因此,即使您可以演示A中X的更改实际发生在B 按时间顺序中读取X之前,也无法保证B 看所做的更改是没有同一对象的同步。
CPU缓存在这里发挥作用; B可能很好地看到X中的陈旧值,因为缓存尚未写回主存储器(
)您的代码可能适用于某些硬件配置,偶尔也会失败。具有松散内存模型的SMP系统特别容易失败(想想DEC Alpha)。
答案 2 :(得分:1)
没有
不保证。
您应该在X上同步以确保完整性。请注意,您应该避免在同步块中包含实际的发送和接收。
Thread A
synchronize( X ) { Thread B
[modify Object X]
[build request A using data from X]
}
[Send a request A over TCP by NIO]
[receive response for request A over TCP by NIO]
[read Object X] // assuming from a synchronized database or collection.
synchronize( x ) {
[handle the response]
}
[call methods in other objects]
如果在线程B中处理响应,请使用X中的状态以确保您可以处理该消息。
如果你需要调用系统的其他部分也使用这样的锁并且可以调用X中的方法,你必须做一些工作以确保不会出现死锁。例如,确保在调用其他对象之前可以放弃锁定。