我知道也许这个问题的答案是显而易见的。但如果有人能给我一个明确的答案,那将是很有帮助的。
问题是: 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所做的修改对线程B是可见的吗?
非常感谢你的帮助。
发布于 2009-06-02 05:58:48
我的猜测是TCP请求不会对线程同步做出任何正式的保证。
也就是说,我认为对于您提出的问题有一个简单的解决方案:可以合理地假设TCP请求至少与获取锁一样昂贵(就性能而言)。因此,您可以将发送/接收封装在synchronized块中,而不会显著影响性能。这将确保线程B将在对象X被修改后看到它。
发布于 2009-06-02 06:23:40
对于这种情况,JMM绝对不做任何保证。除非两个线程在同一对象上同步,否则两个线程之间没有“发生之前”的保证。因此,即使您可以证明A中X的更改实际上是在读取B中的X之前发生的,但不能保证B将看到A所做的更改,而不是同一对象上的同步。
CPU缓存在这里开始发挥作用;B很可能在X中看到陈旧的值,因为缓存还没有写回主内存。
您的代码可能会在某些硬件配置上工作,但在其他硬件配置上偶尔会失败。具有松散内存模型的SMP系统特别有可能失败(想想DEC Alpha)。
发布于 2009-06-02 08:13:13
不是的。
这是不能保证的。
您应该在X上同步以确保完整性。请注意,应避免在synchronized块中包含实际的发送和接收。
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中的方法,那么您必须做一些工作来确保您不会获得死锁。例如,在调用其他对象之前,请确保您可以删除锁。
https://stackoverflow.com/questions/938060
复制相似问题