This week's book giveaway is in the JavaScript forum.
We're giving away four copies of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js and have Paul Jensen on-line!
See this thread for details.
Win a copy of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js this week in the JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

importance of "happens-before"?  RSS feed

 
Peter Chase
Ranch Hand
Posts: 1970
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

As we know, JVMs are allowed to make optimisations that mean code may not execute exactly as written. For instance, threads can have their own quick-access copies of fields, or instructions can be re-ordered for efficiency. (These are the reasons why naive implementation of the Double-Checked Locking idiom doesn't work).

As I understand it, only "volatile" and synchronisation boundaries give guarantees that different threads will all see the values of fields that a naive interpretation of the code would lead us to expect. They do this by enforcing what Sun calls "happens-before" relationships.

In the application on which I work, there is a class with some data in the fields of an object that can be accessed by more than one thread. There is no synchronisation and the fields are not "volatile". However, if one analyses the code, ignoring "happens-before" issues, one can convince oneself that the fields should always have the right values.

I put forward the theory that unexpected field values, due to a lack of "happens-before" relationships, could be the cause of an intermittent, but frequent, misbehaviour that I see in the application.

The experienced developer, whose views I generally respect, to whom I put this theory agreed that it was theoretically possible, but said that he thought it was very unlikely that a frequent misbehaviour could be the result of such problems.

The implication was that failure to enforce "happens-before" relationships was only likely to result in infrequent misbehaviour.

I am wondering whether anyone has any views on this. In particular, have such issues become more important in recent versions of Java? We recently switched from 1.4 to 6.
[ November 15, 2007: Message edited by: Peter Chase ]
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, it does sound plausible that the problems you're seeing are because of memory model issues such as the JVM reordering some operations. And though I don't know details offhand, it's very plausible that this became more significant in recent versions of the JDK. The original memory model was known to have issues, and they were working on revising it for some time before JDK 5 came out with the new rules. I suspect that in JDK 1.4 they may have avoided some optimizations because the memory model was still in flux - while once the model was locked down in JDK 5, it made more sense to pursue more aggressive optimizations.

You may be able to test this theory and perhaps fix it by adding synchronization. Even if this impacts performance, you can at least see if the problems go away. You can even add synchronization that otherwise seems silly, e.g.

Here syncing on a new Object seems silly, because the only reference to the object is local, and there is no chance that any other thread could be syncing on the same object - what's the point of doing it? Well, it does create a memory barrier, preventing instruction reordering from crossing the boundaries of the sync block. Code before the block necessarily happens before code within the block, and code after the block necessarily happens after code within the block. It's still possible to have reordering within the block however. Nonetheless, adding a few memory barriers like this may be enough to fix your problems. If you can put the barriers in the right places.
[ November 15, 2007: Message edited by: Jim Yingst ]
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If, for example, the hot spot engine decided that those fields are accessed often enough to simply keep them in registers, it would very well lead to quite frequent problems.
 
Pat Farrell
Rancher
Posts: 4686
7
Linux Mac OS X VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Yingst:
If you can put the barriers in the right places.



Leaving finding the right places as an exercise to the reader no doubt.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, how specific can I get here? It's Peter's code; I haven't seen it. I deny all responsibility.
 
Peter Chase
Ranch Hand
Posts: 1970
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the views. It's not trivial to try adding the synchronisation, but it sounds like it will be worth trying it.

The synchronized(new Object()) idea is interesting - I'd never thought of that before. In my case, I think there probably is a "proper" object to synchronise on, so I'll do that. Synchronising on an otherwise-unused object, just to get memory barriers, would take rather a lot of commenting in the code!
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!