Is this analysis correct, and how to force flush to main memory in Java by hand after initializing the shared resource as in this particular situation where I do not want or require volatile or synchronized.
It's not possible to not require volatile
or synchronized
. You have to use some form memory synchronization between threads or stuff doesn't work.
You could use a static
initializer as Andrei mentioned (*), or final
, both of which imply a memory barrier. But you have to use something.
You may need to require a synchronized map (Collections.synchronizedMap()) or a CurrentHashMap, but you still need to use volatile
, synchronized
, final
or static
to guard the field itself.
C.f. Java Concurrency in Practice by Brian Geotz, and also this related question on Stack Overflow (note that the OP gets the name of the book wrong).
(* The whole static initializer thing is kinda complicated, and you should read Mr. Goetz's book, but I'll try to describe it briefly: static
fields are part of class initialization. Each static field or static initializer block is written, or executed, by a thread (which could be the thread that called new
or accessed the class object for the first time, or could be a different thread). When the process of writing all static
fields for the first time is done, the JVM inserts a memory barrier so that the class object, with all its static fields, is visible to all threads in the system as required by the spec.
You do NOT get a memory barrier per field write, like volatile
. The class load tries to be efficient and only inserts one barrier at the very end of initialization. Thus you should only use static
initializers for what they're supposed to be for: filling in fields for the first time, and don't try to write entire programs inside a static initializer block. It's not efficient and your options for thread safety are actually more limited.
However, the memory barrier that's part of class initialization is available to use, and that's why, Andrei Amarfii said, the pattern of using a static initialzer in Java is used to ensure visibility of objects. It's important enough that Brian Goetz calls it out as one of his four "Safe Publication" patterns.)