First, you have to understand a little something about the Java memory model. I've struggled a bit over the years to explain it briefly and well. As of today, the best way I can think of to describe it is if you imagine it this way:
- Each thread in Java takes place in a separate memory space (this is clearly untrue, so bear with me on this one).
- You need to use special mechanisms to guarantee that communication happens between these threads, as you would on a message passing system.
- Memory writes that happen in one thread can "leak through" and be seen by another thread, but this is by no means guaranteed. Without explicit communication, you can't guarantee which writes get seen by other threads, or even the order in which they get seen.
At this point, I usually rely on a visual aid, which we call the "two cones" diagram, but which my officemate insists on calling the "two trapezoids" diagram, because he is picky. ready is a volatile boolean variable initialized to false, and answer is a non-volatile int variable initialized to 0.

The first thread writes to ready, which is going to be the sender side of the communications. The second thread reads from ready and sees the value the first thread wrote to it. It therefore becomes a receiver. Because this communication occurs, all of the memory contents seen by Thread 1, before it wrote to ready, must be visible to Thread 2, after it reads the value true for ready.
This guarantees that Thread 2 will print "42", if it prints anything at all.
If ready were not volatile, what would happen? Well, there wouldn't be anything explicitly communicating the values known by Thread 1 to Thread 2. As I pointed out before, the value written to the (now non-volatile) ready could "leak through" to Thread 2, so Thread 2 might see ready as true. However, the value for answer might not leak through. If the value for ready does leak through, and the value for answer doesn't leak through, then this execution will print out 0.
We call the communications points "happens-before" relationships, in the language of the Java memory model.
(Minor niggle: The read of ready doesn't just ensure that Thread 2 sees the contents of memory of Thread 1 up until it wrote to ready, it also ensures that Thread 2 sees the contents of memory of any other thread that wrote to ready up until that point.)
With this in mind, let's look at the Double-Checked Locking example again. To refresh your memory, it goes like this:
The object of the double-checked locking pattern is to avoid synchronization when reading a lazily constructed singleton that is shared between threads. If you have already constructed the object, the helper field will not be null, so you won't have to perform the synchronization.
class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
However, this is only part of the solution. If one thread creates the object, it has to communicate the contents of its memory to another thread. Otherwise, the object will just sit in the first thread's memory. How do we communicate the contents of memory to another thread? Well, we can use volatile variables. That's why helper has to be volatile -- so that other threads see the fully constructed object.
Locking in Java also forms these "happens-before" communication points. An unlock is the sender side, and a lock on the same variable is the receiver side. The reason that doesn't work for (non-volatile) double-checked locking is that only the writing thread ever performs the locking. The whole point of the idiom is that the reader side doesn't do the locking. Without the explicit communication in the form of the volatile variable, the reading thread will never see the update performed by the writer thread.
Let me know if that makes sense.

65 comments:
Hi,
Nice post, you explain very well why the volatile keyword is needed and what are the effects of using it or not using it. Now, the thing about threads using separate memory spaces, I guess it is just artistic license to help you make the point right? :)
IIRC this is only valid with the new Java memory model.
@domingos -- That's an interesting philosophical question. In principle, the definition of a thread is "like a process, but with shared memory". So the memory is certainly shared. But the fact is that you might not be writing to or reading from it when you think.
For example, most processors nowadays have local caches. If one thread is reading from and writing to a cache on one processor, it may not see the same value as another thread writing and reading from another cache on another processor, depending on the processor's memory consistency model.
That's one of the reasons why explicitly doing the communication is so important. One of the things that accessing a volatile variable effectively does on such machines is to say "reconcile the cache with main memory".
But yes, there is definitely a shared memory space. That's how the values "leak through".
@gabriel -- True. Since I was one of the co-authors of the new memory model, I take the liberty of pretending that the old one doesn't exist. :)
the analogy of private memory spaces for threads works really well - in fact it's precisely this property of the java memory model that enables something like Terracotta to work. We use the happens before edges to cross real process boundaries but code is never the wiser because as far as the memory model is concerned it really doesn't matter whether the shared memory is in a single system or many.
Hi Jeremy
If i declare a long/double variable as volatile, will a write to that variable in Thread A be atomic?
Is it possible for Thread B to see corrupt values for volatile long/double types?
Vignesh
RE:
> If i declare a long/double > variable as volatile, will a write to that variable in Thread A be atomic?
Volatile guarantees your double, longs (64 bits) are atomic, though some very, very early (ie well before JSR 133) JVM's messed this up apparently, they were wrong to do so.
So using "volatile" for a variable that is accessed often would cause a lot of cache thrashing, right, since each access to it would cause a sync of all the processors'/cores' caches?
Thus the impact of volatile is bigger on a multi-core system than on a single core?
Thanks anonymous for answering my question.
After Java 5, i think volatile guarantees "Happens Before" like synchronization.So, presence of volatile keyword for a variable ensures that the variables written to before write to volatile variable are not reordered by the compiler even though the other variables are not declared volatile.This is my understanding after reading Jeremy's previous posts on this.
Vignesh
So, if I declare a non-primitive object (like a HashMap) as volatile, the thread caches will synch only if that reference is assigned to a new HashMap (or null)? Would inserts and deletes force synchronization?
(I realize this may not be a good example since any HashMap shared between threads would need to be synchronized regardless)
"Minor niggle: The read of ready doesn't just ensure that Thread 2 sees the contents of memory of Thread 1 up until it wrote to ready, it also ensures that Thread 2 sees the contents of memory of any other thread that wrote to ready up until that point"
But is this behavior just a result of how modern CPU's *enforce* java's memory model? I don't remember if the JMM actually calls for this behavior.
Also, I am curious about your thoughts on Markus's question.
--V
@markus: yes, conceptually a write to volatile normally causes a full cache flush of pending writes, and a read should invalidate the whole cache (preserving dirty cachelines). But this also happens on each lock and unlock operation - it is the same since in both cases a happens-before relationship must be enforced. Technically, I think that a x86 SFENCE is needed _before_ a write to a volatile field, and a LFENCE before a read from a volatile.
That said, optimizations are possible to reduce the synchronization cost.
On the Java side, the write and the read need to be on the same variable - most of the times it does not matter except when static analysis performed by the JVM compiler can prove this is never the case.
On the JVM side, I think a smart JVM would not use any _cache_ flush on an uniprocessor machine. It would just need to actually perform writes of values kept inside registers.
And I also think that a multicore system with a shared cache would not need cache flushes, either.
Can one implement a read barrier with
int a = aVolatileVariable;
return;
a write one with:
aVolatileVariable = 0;
and a full memory barrier with
aVolatileVariable = aVolatileVariable;
? I'm pretty sure the compiler wouldn't be allowed to optimize the otherwise meaningless operation away, but I could have overlooked some detail.
@taylor -- Yep. We were heavily inspired by the DSM research in the early 90's, which I believe Terracotta harks back to (although I haven't looked at Terracotta in detail).
@markus -- Marking fields volatile may or may not involve more thrashing, depending on your processor architecture. For example, in x86, a volatile read requires no additional memory coherence operations to implement (which is a part of why java.util.concurrent is fast on x86). If you are just doing reads on x86, it doesn't really matter whether they are marked volatile or not.
Having said that, YMMV. There is often a cost associated with volatility. Consult Doug Lea's JSR-133 cookbook for a lot of detail.
@anonymous - "So, if I declare a non-primitive object (like a HashMap) as volatile, the thread caches will synch only if that reference is assigned to a new HashMap (or null)? Would inserts and deletes force synchronization?"
Nope. You are just doing a volatile read in that case -- a read of the reference to the HashMap. You have a receiver, but no sender.
As you point out, you would never want to do this, because you would have broken behavior (including the infamous HashMap infinite loop).
@"But is this behavior just a result of how modern CPU's *enforce* java's memory model? I don't remember if the JMM actually calls for this behavior."
It's guaranteed by the memory model. In memory model language, all writes to a volatile field happen-before any subsequent reads of that volatile field. In the language I used in this post, all of those writes are sending, and any subsequent read is receiving from all of them.
@paolo (1): lfences are only required for SSE instructions on x86, so most volatile reads are nops.
I want to underline that there are compiler optimizations that can affect this -- so the JVM has to be careful not to reorder with abandon around loads and stores of volatile fields. So there is still an impact on uniprocessors.
I keep meaning to do a post on synchronization optimizations.
@paolo (2): You have to be careful with this sort of thing. If it turns out that aVolatileVariable isn't accessed by multiple threads, then the VM (or, rather, future VMs) can optimize away the coherence operation, knowing that there is no other side to the happens-before edge / multithreaded communication.
Hi Jeremy,
I find the phrase "memory contents the thread sees" ambiguous... I'm sure it's just me, but what exactly does this mean? memory contents that may be cached in the current scope, memory contents that may be cached anywhere on call stack, or...?
Thanks.
@ Jeremy and Paolo,
if the vm is allowed to optimise it away because it isn't accessed by multiple threads, than it doesn't do any damage. As long as it doesn't allow these read and write barriers to be removed when they should not.
I'm struggling with the same problem. If you want to understand the JMM you need to play on the edge and in some cases fall over. But I would like to know for sure that I don't fall over in this case, so the read/write/full barrier isn't removed when there is some JMM value.
ps:
I came up with the same implementation for read/write/full barrier and would like to know for sure that it works.
I placed the question on the concurrency mailinglist, lets see what the guru's answered.
@anonymous: So, obviously, every time you read anything, it is a memory read. In this case, I mean "anything in the Java heap"; i.e., anything that can be shared between threads. The implementation details of whether this happens to be stack-allocated or whether it is being read out of a write buffer is implementation-dependent (and one of the big reasons that we have a memory model). I hope that answers your question.
@peter -- They generally let me answer these sorts of questions, unless David Holmes gets to them first. :)
If the JMM insists that there will be a happens-before relationship, then the relationship has to be enforced by the JVM (otherwise there is a bug).
Hi,
A question about 'happen-before'. This memory barrier is between 'write' and 'read' only?
I'm a little confused if there are two threads writing to the same volatile variable. Does 'happen-before' still hold?
For example,
Thread #1
answer = 42;
ready = true; // write
Thread #2
ready = false; // write
print answer;
Can I expect to see answer=42 within Thread #2? Or the memory barrier works only write/read?
Thank you.
Also, some commentors mentioned of HotSpot run-time optimization. Can someone point me to the right direction on how I can learn more about it. I tried Sun 1.6.10 debug JVM with -XX:+PrintOptoAssembly option but hard time reading the output. I want to learn more about it. I am getting interesting result regarding hotstop and infinite loop and trying to understand more about it. Thanks in advance.
@stinky -- no, it doesn't work write/write. It is spec'd not to work that way. Think about it this way -- how would you know which write occurred first? You have to find some way to provide that guarantee.
The -XX:+PrintOptoAssembly output is fairly low level; I don't know of any clear reference on it.
(Note: I'm answering to posts @paolo (1) and @paolo (2)).
@Jeremy(1): I had such a feeling about LFENCE (i.e. that it wasn't needed most of the time), but the Intel manuals are not that easy to follow about this. What you said about volatile reads, however, is really important (and I hope it extends to x86_64).
@Jeremy(2): you are right about the aVolatileVariable thing. I forgot to mention that the plan was to do that onto a static volatile, creating static members:
MemoryBarrier {
private volatile Object dummyVar;
public readBarrier();
public writeBarrier();
public fullBarrier();
}
with the bodies I wrote in my previous post.
One could also make them nonstatic, to allow conceptually independent memory
barriers to be executed. Unlike the existence of separate locks, that's useful just to make the source self-documenting, unless one is using a useless barrier, and the compiler can prove that (which means you
really screwed it up).
I'm used to memory barriers from C programming, and I have some reasons for
bringing them to Java: in some cases, doing this is much simpler than making
"almost immutable" data, which is not set by a constructor, actually immutable (in some cases you'd have to rework the class diagram just for this, or create horrible dummy classes, like I did a couple of times), and maybe it can be faster than making a field volatile if it is set just at one point (if one is able to avoid doing a read barrier for each read access). I'm not sure about the last point though.
love your blog good stuff
@paolo: There is a better summary of the x86 mm from Rick Hudson and Bratin Saha. I can't find it online, but there is an informative video by the former here: http://www.youtube.com/watch?v=WUfvvFD5tAA
As for the other case, I think that what you want is probably an interface that looks like:
SomeClass.publish(foo);
which will safely publish foo without implying fence semantics. The JMM has this for final fields, but we've never worked this out for non-finals.
Doug Lea is currently talking about a Fences API:
http://g.oswego.edu/dl/concurrent/dist/docs/java/util/concurrent/atomic/Fences.html
But I think that it will be very difficult for the average programmer to use, and we'd be much better off with something that actually encapsulated the use cases correctly.
@mikey: Thanks!
Hi everyone,
I am wondering if I can use the volatile keyword for cache of singletons.
Suppose I have a search engine framework, and there are several types of searches. For each type, there is a search engine class. And I want to keep only one instance of search engine for each type in memory. So I will use a HashMap as the cache, with search type as the key, and search engine instance as the value.
Now there are two concerns. The first is that if a thread may get a search engine instance which is not fully initialized (the same problem as in Double-Checked Locking). The second concern is that after a search engine is created and put in the cache (HashMap), can other thread get it from the cache.
I came up with the following code, let's see if there is any problem there.
public class SearchEngineStore{
//I don't use ConcurrentHashMap, because at worst only few threads (at the beginning) don't see the updated cache and have to enter the synchronization block.
private static Map<String, ISearchEngine> cache = new HashMap<String, ISearchEngine>();
private volatile static ISearchEngine newEngine = null;
public static ISearchEngine getEngine(String searchType){
ISearchEngine engine = cache.get(searchType);
if (engine == null){
synchronized(cache){
engine = cache.get(searchType);
if (engine == null){
newEngine = SearchEngineFactory.newInstance(searchType);
//since the newEngine is a volatile variable, the next 2 steps shouldn't be executed until the initialization in the above step finishes. (Am I right?)
engine = newEngine;
cache.put(searchType, engine);
}
}
}
return engine;
}
}
There are various problems in that code.
IMHO the simplest thing is to avoid any tricks (like that volatile field, which is a clear hack) and use ConcurrentHashMap. If you want more speed, try with Cliff Click's version of ConcurrentHashMap.
But before doing that, consider if you need at all to optimize this. Do you have a performance problem at all? If not, just use synchronize the straight way: no access to shared variables except under synchronized.
Basically, your error is that you think implicitly synchronizing the write side is enough. Appropriate locking should be inserted also on the read side - I'll refer to this below.
First, you do have exactly the Double-Checked Locking problem. If the first unsynchronized map lookup succeeds, nothing guarantees you that the effects of the object constructor are visible, even if insertion is done under a lock, because the read side can run without synchronization.
Also, in some cases, even if the Map were thread safe by itself, if it does not give happens-before guarantees, you can still get the above result. Cliff Click's NonBlockingHashMap may be such an example (but I don't know, its documentation is not clear on this). More important, the write and the read need to be atomic, so you need in any case a synchronized block to make them indivisible.
Then, there is this comment:
//I don't use ConcurrentHashMap, because at worst only few threads (at the beginning) don't see the updated cache and have to enter the synchronization block.
You are accessing an HashMap through a data race, because it's shared and you read it without locks, and you should not. Even the assumption that the updated value will eventually be visible is not guaranteed by the JMM (if the value is copied into a register and kept there, this might show up in practice, in simpler examples).
Then:
//since the newEngine is a volatile variable, the next 2 steps shouldn't be executed until the initialization in the above step finishes. (Am I right?)
Maybe you are right (I think the reordering may be possible actually), but the read side has no read of newEngine, so it should be allowed to see a race going on, and on systems were read barriers are needed, the problem will show up in practice.
Another thread doing an insertion will read newEngine and so it'll be safe - but that's already guaranteed by the synchronized block.
In fact, replacing the innermost if with this block will produce no change:
if (engine == null){
engine = SearchEngineFactory.newInstance(searchType);
cache.put(searchType, engine);
}
since it is contained into synchronize.
Writes done before a volatile write operation A are visible for sure after you do a volatile read that see the result of action A. Writes done after A may be moved before it.
Actually, thinking in terms of happens-before encourages thinking in terms of reorderings, which can be more complicated.
It's simpler to think "if no data race exists, I can expect safely sequential consistency", i.e. each action will be executed atomically, they will be visible in the same total order for every thread, and there will be no visible reordering. Like if all threads were multiplexed on a single processor. That's more or less the definition used by the new C++ Memory Model, which will be a simplified version of the Java one.
@Zixin - Paolo is right about that code. It simply won't work. It won't work even regardless of the semantics of volatile fields, because the get() can happen when the HashMap is in an inconsistent state, which can cause crashy behavior.
Paolo and Jeremy,
Thanks for your comment. Let me make sure I understand you correctly.
1. ConcurrentHashMap (or other synchronized version of HashMap, or synchronization block for the read/write) must be used, otherwise, the hash map may just crash.
2. Even the thread doing an insertion flushes changes to the main memory when it exists the synchronization block, the thread doing a read without synchronization may not see all the effects: it may see only the HashMap.put() effect but not the object initialization. This results in a successful "get" from HashMap with an uninitialized object (just the same problem in DCL). That means, my attempt of using volatile variable to make sure the read thread sees the fully initialized object just failed.
3. It seems there is no other solution for this particular case than making the whole method synchronized. Do we?
Paolo, are you sure that "Writes done after a volatile write operation may be moved before it"? For example:
Step 1. Set A=1
Step 2. Write to a volatile variable
Step 3. Read from the same volatile variable
Step 4. Set A=2
If step 4 can be moved up, then how can we guaranteer the state when the volatile variable is read?
Thanks again!
@zixin - The happens-before relationship only exists between a write of a volatile and a subsequent read of the same volatile. Since no one on the reader side is doing a read of the volatile, you won't get the guarantees you want.
For this case, you could try using ConcurrentHashMap with putIfAbsent:
private static Map<String, ISearchEngine> cache = new ConcurrentHashMap<String, ISearchEngine>();
ISearchEngine engine = cache.get(searchType);
if (engine == null) {
engine = SearchEngineFactory.newInstance(searchType);
cache.putIfAbsent(engine);
}
If you really can't handle ever accidentally creating a new instance of SearchEngine, then you could use synchronization for mutual exclusion here:
private static Map<String, ISearchEngine> cache = new ConcurrentHashMap<String, ISearchEngine>();
...
ISearchEngine engine = cache.get(searchType);
if (engine == null) {
synchronized (cache) {
engine = cache.get(searchType);
if (engine == null) {
engine = SearchEngineFactory.newInstance(searchType);
cache.put(engine);
}
}
}
The fact that it is a ConcurrentHashMap papers over the memory model difficulties.
@Zixin
1st part: I agree on most points, at a basic level. I would correct point #3 to say "there is no _simple_ solution to do that, but moreover it's just not worth it".
But you may wrap a ConcurrentHashMap to handle failed lookups by creating the new value - that's the only simple&clean solution, which does not clutter sources. See http://code.google.com/p/concurrentlinkedhashmap/wiki/SelfPopulatingCache
> 2. Even the thread doing an insertion flushes changes to the main memory when it exists the synchronization block, the thread doing a read without synchronization may not see all the effects: it may see only the HashMap.put() effect but not the object initialization. This results in a successful "get" from HashMap with an uninitialized object (just the same problem in DCL).
That's correct, as long as "may" is intended as "that's one of the various possible reorderings" - it's simpler to assume undefined semantics for data races. Semantics are actually defined, but relying on them is a bad idea, and I'll let Manson elaborate on this if ever needed. Never studied them indeed.
> That means, my attempt of using volatile variable to make sure the read thread sees the fully initialized object just failed.
Yep :-(.
2nd part: in your example, step 4 cannot be moved up just because of the read.
@Jeremy: I also hit this kind of problem, which is fairly common. Since I was generating class files with Javassist, I couldn't use plain putIfAbsent per the first step. Also, I wanted to absolutely avoid synchronization on a common lock.
The solution I came up with was to use directly putIfAbsent() to insert a placeholder, and do the computation if the insert succeeds, calling notify on the placeholder at the end; on failure, if a placeholder was found, wait on it for the computation to complete and return the result; if a non placeholder object was found, return it.
All this is encapsulated inside the implementation on top of a ConcurrentMap; the client code performs a cache lookup, a computation and a cache update. It looks like the code is very similar to the one for SelfPopulatingCache, except for the client API, and for the fact that I didn't know I could use Future instead of writing explicit synchronization code; however, I could guarantee that notifyAll() is not needed nor called (each awaken thread notifies the next one just after the wait on the placeholder and before releasing the lock on it).
Any opinions on the two alternatives?
Jeremy,
I think it's better to change your example which uses "putIfAbsent" to the following:
......
engine = cache.putIfAbsent(engine);
......
This makes sure that the method always returns the same instance (the one put in the ConcurrentHashMap), then the extra engine may just be garbage collected.
Your next example works because ConcurrentHashMap uses volatile variables, which guaranteers that search engine initialization happens-before the insertion into the hashmap, which happens-before the read from the hashmap.
Thanks you two! I learned a lot.
Thumbs up to both points! It's nice that you learned a lot ;-), it's rewarding for the time one spends :-)
About the first point: Jeremy posted the code up to the insertion, so the buggy behaviour you get when inserting Jeremy's comment in the original method was not intended.
The placeholder approach has an extra benefit - bulk gets. You can perform a getAll() operation that places proxies map, perform the bulk task, and run all the proxies to warm them. Any subsequent calls looking for one of the proxied items is blocked from doing unnecessary work.
This is a fairly nice optimization if you are backing the local cache with a remote caching layer. That's how my production version of the tutorial's SelfPopulatingMap works (its a fairly simple enhancement).
I'm sorry, but I've got trouble understanding your comment - could you please elaborate much more?
What's the point of the proxies and what does it mean "warming the proxies"? How are subsequent calls blocked (wait on a semaphore), and what is the unnecessary work you save?
How is this all related to the use case you describe about a local remotely backed cache?
Sorry, its my fault for not being clear enough.
Imagine you need to retrieve 10 objects, say to show on a paginated form. You could retrieve each sequentially, perhaps with 3 found and 7 needing to hit the data store. The worst case is O(n).
Now, what if you add a getAll() method to the map and have a BulkEntryFactory? The worst case is now O(1), as they are retrieved in parallel. Even if all you can do is get one at a time from the system of record (database), you might put in place a 2nd-level cache (like memcached) and still get O(1) if its warmed. So there's a nice performance boost.
To implement, you could perform the operation and populate the map afterwards. But, if you're retrieving #1-10 and another request wants #6, its duplicate effort to miss and load the data. Instead you can place ten proxies into the map so that any subsequent request blocks on the proxy waiting for it to load. The bulk task is executed and the proxies are run to warm their slot from the bulk's response. This also unblock anyone waiting, giving you both a better hit rate and O(1) efficiency.
Ok, thank you very much, that makes a lot of sense.
But how does the API allow the map to know all the keys? Or is the method getAll(Collection keyCollection)?
Finally, it seems you don't replace the proxy with the actual element, do you? OK, I can see that in a map with eviction one might want to have a proxy always in place (when it is first installed) with a get() method, to reduce write access (and possibly lock contention) on the map.
Yes, I was thinking that getAll() would accept a collection of keys. This would follow the same idiom as putAll() and removeAll() methods in the collections framework.
And yep, once the proxies are warmed, there's no need to replace them. I can post the code if interested.
I love lively discussion on my blog, so I don't want to seem as if I am discouraging it, but I wonder if you folks have seen the concurrency-interest mailing list:
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
It's a great place to ask this sort of advice from a wide range of experts, as much as my ego would make me believe that I am a good single-source for this stuff.
I replaced the tutorial's quick-n-dirty implementation (buggy, I'm sure) with the version that I use in production. This includes the bulk retrieval strategy described above.
How to implement a SelfPopulatingMap
I think I have the responsibility to correct an error I made in one of my previous comments. The following code is wrong:
......
engine = cache.putIfAbsent(engine);
......
It should be:
......
ISearchEngine previousEngine = cache.putIfAbsent(engine);
if (previousEngine != null)
engine = previousEngine;
......
That's to say, method putIfAbsent() returns null if there is no value of the specified key in the map before the insertion. It won't return the inserted value.
helper = new Helper();
To call this function from foo, constructor should be public. If its a public constructor, where is the point of Singleton ?.
Helper object can be created very much from its public constructor isnt ??
If Foo is a separate class, for that to make sense, the simplest case is when Helper is an inner class, or a package-private class in the same package (in this case, you have something like a per-Foo-instance singleton).
Otherwise, I think that you can replace "Foo" by "Helper" in the class declaration and make getHelper static, so that you get the singleton instance with a call to Helper.getHelper().
In both case, you get a meaningful example.
Hi Jeremy,
Could you please give sample java code with threads to experience the use of volatile in java.
Thanks.
@SmarTechSrini - what kind of thing did you have in mind?
Hi Jeremy,
This is the code i used.
Even now only one object is created (Value of one thread is seen by other)
without using the volatile keyword.
Is my understanding right?
If i am wrong, could you please give me some more explanation or sample code to experience the importance of volatile keyword.
Thanks.
class Foo {
private Helper helper = null;
public Helper getHelper() {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
synchronized (this) {
if (helper == null) {
helper = new Helper();
System.out.println("Creating new helper......");
}
}
return helper;
}
class Helper {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
private boolean status;
}
public static void main(String args[]) {
final Foo foo = new Foo();
//For concurrency using thread technique
for (int i = 1; i < 1000; i++) {
new Thread() {
public void run() {
for (int i = 1; i < 100; i++) {
new Thread() {
@Override
public void run() {
foo.getHelper();
}
}.start();
}
}
}.start();
}
}
}
Output:
run:
Creating new helper......
BUILD SUCCESSFUL (total time: 45 seconds)
@SmarTechSrini - this pattern is called single-check, and it works because you don't access the helper field without at least holding the lock at some point. You are likely to have some problems if you start trying to call setId from multiple threads without synchronization, though.
Okay.
I'll try.
If you have any java code (concurrency) which behaves differently for two scenarios:
1. With volatile keyword.
2. Without volatile keyword.
Please post the java code so that i will get the exact usage and understanding on "volatile" keyword in concurrency.
Thanks.
@SmarTechSrini - The behavior of volatile depends on your particular architecture and VM. The example whose weird behavior you see the most when it doesn't have volatile in it is the visibility example in my post on Atomicity, Visibility and Ordering, in the class LoopMayNeverEnd.
http://java.sun.com/javase/7/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility
states that synchronized guarantee happens-before. I feel there is no need for volatile.
http://java.sun.com/javase/7/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility
As per above link synchronized method/block both guarantee happens-before. double locking using volatile field and synchronized block is not needed.
@miten - To oversimplify: locks are slow, and volatile is fast.
Hello Jeremy,
regarding your example, I think it would be very important for "beginners" to clarify if the variable "answer" also has to be volatile or not!
In your example the variable "ready" needs to be volatile in every case. But what about the variable "answer"? does the "volatile ready variable" implicitly make "answer" also volatile? thats nowhere stated in your explanation or does the programmer explicitly have to declare answer volatile to get the "happens before" relationship.
it would be kind if you can answer this question.
thanks!
@Anonymous - The happens-before relationship is provided by ready; the visibility of answer is guaranteed by the fact that ready was made made volatile.
Or, another way: everything that happens-before the write to ready is ordered before and visible to everything that happens after a read that sees that write. The write to answer is therefore ordered before and visible to the read of answer.
Hi Jeremy:
Just need to make sure, So for the case of Collections.synchronizedMap which return synchronized-wrapper map.
If thread-A put something to this synchronized-Map,
Thread-B can read the value that thread-A has put into the map (happen-before).
Is this right? Because synchronizedMap Wrapper use the synchronized-block on the same mutex-object monitor for all map access-methods.
Another question is ... For all concurrent-collection classes in java.util.concurrent package, has this happen-before semantic right?
Br,
Suttiwat
Oh, sorry my 2nd question has been answered in java.util.concurrent package-summary.html already.
@Suttiwat - yes, that's right.
Post a Comment