"I'm not back." - Bill Harding, Twister
"I'm not back." - Bill Harding, Twister
Originally posted by Jim Hurne:
What I am doing is initializing an immutable, non-singleton object and storing it in a static field. Multiple threads can (and will) access the static field and initialization code. Maybe an example would be best:
A couple of notes:
1) Creation of the object is expensive, thus the above code is an attempt to share the object with multiple threads.
2) I don't care if multiple threads get some "extra" copies of the immutable object, or if extra copies are created and discarded right away. Threads getting extra copies will not harm the execution of the application (the cost is only memory and some performance).
3) Because of #2, at first glance, it does not appear that the code needs synchronization.
4) However,the code is still vulnerable to out-of-order writes, and it IS possible for a thread to obtain a partially-constructed Immutable.
In Java 5, volatile would fix the problem. Is there anything I can do in Java 1.4, aside from synchronizing the entire getInstance() method?
[JY]: Yes, there's the initialization-on-demand holder idom.
[BC]: Well I suppose you could try something with ThreadLocal.
"I'm not back." - Bill Harding, Twister
Originally posted by Jim Yingst:
[The ThreadLocal solution is interesting. One issue is that if you've got a thread pool of 100 threads, you'll initialize "loaded" 100 times. And then you'll end up reloading about 100 times (roughly averaged) whenever the lastChanged times get high enough. That may well be acceptable, or it may not.
Originally posted by Jim Hurne :
I took a peak at the source for AtomicReference in the backport
Originally posted by Jim Hurne:
[BC]: Well I suppose you could try something with ThreadLocal.
I'm still trying to reason out whether or not this approach would work, or rather that it guarantees that a thread can not obtain a partially constructed Immutable.
"I'm not back." - Bill Harding, Twister
[BC]: I thought AtomicReference was only in 1.5+, and hence not useful here. Has it indeed been backported?
[JY]: Do you have definite reason to believe that synchronization is a problem here? Many people have caused themselves a great deal of needless suffering by trying to avoid synchronization when they didn't have to. It's worth considering, I think.
Map example = null;
synchronize(new Object()) {
example = new HashMap();
}
Can help create the same types of "memory boundaries" that the volatile keyword creates. Is this true?
I believe so, yes. The sync block there obviously doesn't do any useful blocking of other threads, but it does force all variables to be refreshed before they're used again.
"Eagles may soar but weasels don't get sucked into jet engines" SCJP 1.6, SCWCD 1.4, SCJD 1.5,SCBCD 5
"I'm not back." - Bill Harding, Twister
[JY]: If loaded is null, then synchronized(loaded) will throw a NullPointerException.
[CH]: There is an issue I believe with this trick in Java 6+ in that the your memory barrier can be optimized away...
"I'm not back." - Bill Harding, Twister
The Java Memory Model says that one thread exiting a synchronized block happens-before another thread enters a synchronized block protected by that same lock; this means that whatever memory operations are visible to thread A when it exits a synchronized block protected by lock M are visible to thread B when it enters a synchronized block protected by M, as shown in Figure 1. For synchronized blocks that use different locks, we cannot assume anything about their ordering -- it is as if there was no synchronization at all.
"I'm not back." - Bill Harding, Twister
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime. |