views:

169

answers:

3

I know maybe the answer to the question is obvious. But if anybody can give me a definitive answer, that would be helpful.

The question is : whether the java NIO package can provide some memory consistency assurance?

The scenario is :

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]

Does the modification made by thread A is visible to thread B if there isn't any synchronization/safely reference pulication between thread A and Thread B by the application.

Thanks a lot for your help.

+4  A: 

My guess is that a TCP request does not make any formal guarantee as to thread synchronization.

That said, I think there is a simple solution to the issue you are raising: it is reasonable to assume that a TCP request is at least as expensive (perofrmance-wise) as acquiring a lock. Therefore, you can enclose the send/receive in a synchronized block without a significant performance penalty. This will ensure that thread B will see object X after it was modified.

Itay
+4  A: 

The JMM categorically makes no guarantees with regards to this scenario. Unless the two threads synchronize on the same object there is no "happens-before" guarantee between the two threads. So even though you can demonstrate the the changes to X in A actually happen before the read of X in B chronologically, there is no guarantee that B will see the changes made be A absent a synchronization on the same object.

CPU caching comes into play here; B may very well see stale values in X because caches have not been written back to main memory (yet).

You code may work on some hardware configurations and very occasionally fail on others. SMP systems with loose memory models are especially likely to fail (think DEC Alpha).

Software Monkey
A: 

No.

It's not guaranteed.

You should synchronize on X to insure the integrity. Note that you should avoid including the actual sending and receiving in the synchronized block.

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]

If the handling of the response in thread B, use a state in X to make sure that you can handle the message.

If you need to call other parts of the system that also uses locks like this and can call methods in X, you have to do some work to make sure that you wont get a deadlock. For instance, make sure that you can drop the lock before calling other objects.

KarlP