aspose file tools*
The moose likes Threads and Synchronization and the fly likes Understanding Volatile & Synchronized Visibility Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Understanding Volatile & Synchronized Visibility" Watch "Understanding Volatile & Synchronized Visibility" New topic
Author

Understanding Volatile & Synchronized Visibility

Roland Drake
Greenhorn

Joined: Jun 14, 2008
Posts: 4
Greetings,

I'm trying to really understand the semantics of volatile and synchronized when it comes to visibility.



My question is--why does the snippet above work? I can understand if it works by marking stopRequested volatile. However, the one I marked volatile is the member "a".

JSR 133 says: "Everything that is visible to thread A just before it writes to volatile variable v will be visible to thread B when it reads from volatile variable v."

But the main thread in the snippet above never "writes" to volatile variable a. It just reads and then use the reference to write to stopRequested, which is not volatile. What gives?

Second question, there's another way to make the snippet work:



Now--again, why does this work? If I understand correctly, whatever is visible from thread A is guaranteed to be visible from thread B if they're entering/exiting synchronized blocks guarded by the same lock. In this case the main thread does not even have a synchronized block to execute. Why does thread FOREVER see the change in value then?

Thanks!
Roland
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19696
    
  20

Volatile and synchronized have NOTHING to do with visibility.

Classes A and StopThread are both in the same file, and therefore in the same package. Since there is no visibility modifier (private, protected or public) for stopRequested, it gets "default" visibility. That means that all code in the same package can access the variable.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Wirianto Djunaidi
Ranch Hand

Joined: Mar 20, 2001
Posts: 210

What the JSR talking about is not the accessibility visibility, but the memory isolation visibility among threads.

If you are familiar with Database isolation, the analogy is having a variable marked as volatile is equivalent of having read uncommitted on the variable. So when you change the variable in thread A, thread B will read the changes right away. If you do not have volatile declared on the variable then it is up to the JVM memory management to flush the changes, so there is a possibility that thread B might read a stale value.

When you are using synchronized, that is similar to having serialized transaction on the database. And any entrance/exit from synchronized block will automatically force the JVM memory management to sync the value so the next thread will read the latest value.

I hope that make sense. I'm not too good at explaining things, especially when it is complex thing like concurrency.

Addendum: Both of your example does not show case the difference of using volatile or synchronized in the visibility. Actually you can see it clearly with classic concurrency sample of 2 threads running with thread A keep changing the variable while thread B tries to read them.
[ June 16, 2008: Message edited by: Wirianto Djunaidi ]
Roland Drake
Greenhorn

Joined: Jun 14, 2008
Posts: 4
Originally posted by Rob Prime:
Volatile and synchronized have NOTHING to do with visibility.

Classes A and StopThread are both in the same file, and therefore in the same package. Since there is no visibility modifier (private, protected or public) for stopRequested, it gets "default" visibility. That means that all code in the same package can access the variable.


Rob Prime, you were joking, right? Please tell me you were joking. I see you got 100% and 91% for your SCJP, there's no way you weren't joking when you said something like this.
[ June 16, 2008: Message edited by: Roland Drake ]
Roland Drake
Greenhorn

Joined: Jun 14, 2008
Posts: 4
Originally posted by Wirianto Djunaidi:
What the JSR talking about is not the accessibility visibility, but the memory isolation visibility among threads.

If you are familiar with Database isolation, the analogy is having a variable marked as volatile is equivalent of having read uncommitted on the variable. So when you change the variable in thread A, thread B will read the changes right away. If you do not have volatile declared on the variable then it is up to the JVM memory management to flush the changes, so there is a possibility that thread B might read a stale value.

When you are using synchronized, that is similar to having serialized transaction on the database. And any entrance/exit from synchronized block will automatically force the JVM memory management to sync the value so the next thread will read the latest value.

I hope that make sense. I'm not too good at explaining things, especially when it is complex thing like concurrency.

Addendum: Both of your example does not show case the difference of using volatile or synchronized in the visibility. Actually you can see it clearly with classic concurrency sample of 2 threads running with thread A keep changing the variable while thread B tries to read them.

[ June 16, 2008: Message edited by: Wirianto Djunaidi ]


Thanks Wirianto for the reply. I know what volatile is supposed to do. The first code snippet in my original post was a modified form of Joshua Bloch's example in Effective Java 2nd ed.

If stopRequested is just a boolean volatile member, I understand what is going on. What I don't understand is if I modify it so that stopRequested is a member of A, and it is the A member that is marked volatile.

Also, I know what synchronized is supposed to do with the flushing. What I don't get is that JSR 133 guarantees this for threads executing synchronized blocks on the _same lock_. But apparently _any_ synchronized block will flush the memory too, as can be seen from my 2nd code snippet.
Wirianto Djunaidi
Ranch Hand

Joined: Mar 20, 2001
Posts: 210

Roland,

Ahh, I see what you mean now. To be honest, I do not know the definitive answer.

But if I have to guess I would say because it is easier to implement. Because synchronized block allows arbitrary lock object. It means you can have multiple synchronized block with different locks throughout your code which might be accessing/manipulating same variables inside it. I guess it will be too much hassle for them to keep checking on which lock object is being used by which thread during runtime and which common variables they might be manipulating, they just flush it on any.
Chris Hurst
Ranch Hand

Joined: Oct 26, 2003
Posts: 416
    
    2

Synchronization may cause a memory barrier if it is required to ensure happens before ordering, it may not if it is not required as its a waste. Some processors OS's don't require flushes as such and only have to worry about byte code re-ordering. JSR 133 talks abut 'happens before ordering' which is not the same thing as a memory barrier though they are strongly related and may boil down to the same thing in a given scenario. A memory barrier is a kind of side effect of happens before ordering.

I've posted examples on this previously but if you sync on unrelated objects as an example its possible for there to be no memory barrier e.g.

{
object o = new Object ();
// this can be optimised away as nothing else can sync on it
synchronized (o) {}
}

Does NOT guarantee a cache flush, which again is why we are all strongly advised to stop thinking in terms of cache flushing (as one isn't required to comply with JSR-133) and only think in terms of happens before ordering.


"Eagles may soar but weasels don't get sucked into jet engines" SCJP 1.6, SCWCD 1.4, SCJD 1.5,SCBCD 5
Roland Drake
Greenhorn

Joined: Jun 14, 2008
Posts: 4
Thanks Chris, Wirianto! I think I got this clearer now.

Roland
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Understanding Volatile & Synchronized Visibility