【问题标题】:Java Memory model questionJava 内存模型问题
【发布时间】:2009-06-02 05:53:35
【问题描述】:

我知道这个问题的答案可能很明显。但如果有人能给我一个明确的答案,那将很有帮助。

问题是: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 可见。

非常感谢您的帮助。

【问题讨论】:

    标签: java memory model io


    【解决方案1】:

    我的猜测是,一个 TCP 请求并没有对线程同步做出任何正式的保证。

    也就是说,我认为您提出的问题有一个简单的解决方案:可以合理地假设 TCP 请求至少与获取锁一样昂贵(性能方面)。因此,您可以将发送/接收包含在同步块中,而不会显着降低性能。这将确保线程 B 在对象 X 被修改后能够看到它。

    【讨论】:

      【解决方案2】:

      JMM 明确 对这种情况不做任何保证。除非两个线程同步在同一个对象上,否则两个线程之间没有“先发生”保证。因此,即使您可以证明 A 中 X 的更改实际上发生在 B 中的 X 读取之前按时间顺序,也不能保证 B 会看到所做的更改同一对象上缺少同步。

      CPU 缓存在这里发挥作用; B 很可能会在 X 中看到陈旧的值,因为缓存还没有写回主内存。

      您的代码可能适用于某些硬件配置,但偶尔会在其他配置上失败。具有松散内存模型的 SMP 系统特别容易失败(想想 DEC Alpha)。

      【讨论】:

        【解决方案3】:

        没有。

        无法保证。

        您应该在 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 中的方法,您必须做一些工作以确保不会出现死锁。例如,确保在调用其他对象之前可以解除锁定。

        【讨论】:

          猜你喜欢
          • 2013-05-02
          • 2019-07-20
          • 2012-04-27
          • 2015-02-06
          • 1970-01-01
          • 1970-01-01
          • 2020-02-02
          • 2013-08-07
          • 1970-01-01
          相关资源
          最近更新 更多