aspose file tools*
The moose likes Threads and Synchronization and the fly likes Behaviour of Volatile variables Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Behaviour of Volatile variables" Watch "Behaviour of Volatile variables" New topic
Author

Behaviour of Volatile variables

Muhammad sibtain
Greenhorn

Joined: Aug 31, 2001
Posts: 17
Hi
I have build an example to understand the behaviour of volatile variables but it is working just like an instance variable. I am not able to understand the behaviour of volatile variable. I will be glad and thankfull if you explain me how i can take advantage of volatile variables and how i can see the bahaviour. An example with the explanation will also be very helpfull for me if you can put a bit extra time.
My Practice example:
====================
public class VolatileTest {
volatile int x=5;
public static void main(String[] args) {
VolatileTest vt1 = new VolatileTest();
VolatileTest vt2 = new VolatileTest();
VolatileThread vThread1 = new VolatileThread(vt1);
VolatileThread vThread2 = new VolatileThread(vt2);
vThread1.start();
vThread2.start();
System.out.println("Exiting From Main Thread");
}
public synchronized void changeVolatile(){
System.out.println(Thread.currentThread().getName()+"-"+ ++x);
}
}
class VolatileThread extends Thread {
VolatileTest vt;
public VolatileThread(VolatileTest vt) {
this.vt=vt;
}
public void run() {
for(int x=0;x<10;x++) {
vt.changeVolatile();
try {
sleep(1000);
}
catch(InterruptedException iex) {
}
}
}
}

Regards
Muhammad sibtain Arain
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
If this dosn't help please let me know.
A volatile variable when used is supposed to be directly loaded from memory every time.
For example if you are using a value that is above 32 bits such as a double or long it is not an atomic operation. Meaning that it can be swiped out of the processor in mid altercation of data.
So, if 2 threads were working on a value such as double
x = 33333333.333333 one thread can change part of the number have the number swipped out and the 2nd thread can then alter the data again getting totaly wrong values for each thread and ending up with corrupted number. Volatile is supposed to prevent this from happening by making it an atomic operation.
For object references I belive it forces a lookup of the reference each time before that object is accessed.
If I am mistaken please correct me. I hope that helps
Marcela Blei
Ranch Hand

Joined: Jun 28, 2000
Posts: 477
"JavaJMan",
your name is not valid as per the Javaranch name conventions. Please refer to the document located here
Jarrod Knox
Greenhorn

Joined: Sep 10, 2001
Posts: 1
Changed JavaJMan to this name now
Girish Pednekar
Greenhorn

Joined: Aug 10, 2001
Posts: 14
Muhammad,
You might want to elaborate on your sample code as to what is the current output and what output you are expecting.
Looking at the code, you have 2 instances of VolatileTest() and each thread is referring to a distinct instance of VolatileTest() thereby referring to distinct instances of 'x' variable. Someone correct me if I'm wrong, but the sychronized keyword is not playing any role here since both the threads are acting on seperate instances of VolatileTest. when ++x is encountered, the x variable for that corresponding instance of VoltileTest (vt1 ot vt2) is loaded from memory but since only one thread is accessing and modifying that variable this operation is redundant. Using only one instance of vt instead of 2 will make sure both the threads are modifying the same variable x. it would be interesting to see the ouput after making this change.
thanks,
GP
Muhammad sibtain
Greenhorn

Joined: Aug 31, 2001
Posts: 17
Thanks JJMan
I Think i need more explantion about
1. Atomic Operation
2. Why only for those types that are of greater than 4 bytes
3. What do you mean by Mid Altercation of Data
4. If i am not wrong you have said that volatile make operations atomic
5. for volatile object referencesthe in what sences verification of the object will take place.
I will be glad if you explain me graphically
Regards
Muhammad Sibtain Arain

Originally posted by JavaJMan:
If this dosn't help please let me know.
A volatile variable when used is supposed to be directly loaded from memory every time.
For example if you are using a value that is above 32 bits such as a double or long it is not an atomic operation. Meaning that it can be swiped out of the processor in mid altercation of data.
So, if 2 threads were working on a value such as double
x = 33333333.333333 one thread can change part of the number have the number swipped out and the 2nd thread can then alter the data again getting totaly wrong values for each thread and ending up with corrupted number. Volatile is supposed to prevent this from happening by making it an atomic operation.
For object references I belive it forces a lookup of the reference each time before that object is accessed.
If I am mistaken please correct me. I hope that helps

marilyn murphy
Ranch Hand

Joined: Aug 28, 2001
Posts: 84
>I Think i need more explantion about
>1. Atomic Operation

Bill Brogden says:
An atomic operation is one that the CPU can perform with no chance of being interrupted. In current 32 bit implementations of Java, reading or storing a 32 bit or smaller primitive value is an atomic operation. Reading or storing long or double primitive values, which are 64-bits long, is not an atomic operation on current 32-bit systems.

>2. Why only for those types that are of greater than 4 bytes

See previous answer

>3. What do you mean by Mid Altercation of Data

In theory, a Thread could store part of a 64-bit primitive and then be suspended by the Thread scheduling mechanism, leaving a bad value for the variable in memory.

>4. If i am not wrong you have said that >volatile make operations atomic

"volatile" does not make changes atomic.

In theory, declaring a field "volatile" notifies the JVM that the value of the field may change unpredictably. In this case, the JVM will not give each thread a working copy of the field. Instead, all thread operations will synchronize on the field's master copy.

However, Philip Heller states that the "volatile" modifier is not considered reliable.
[This message has been edited by marilyn murphy (edited September 14, 2001).]
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

You will rarely use volatile variables. I think primarily they will be used when you have Some hardware that will update a variable, and you want to see the update immediately.
Say you have some hardware calculator java is controlling. When you put in a value, it processes it, But not untill you put another value in another buffer.
So
a =5;
b =6;
When the hardware sees b get a value it will perform an operation and store its value in c. Now if the variables are not volatile, there is no guarantee that a=5 will actually take place before b=6 since the compiler has the freedom to rearrange the order of these commands. If they were BOTH volatile, they could not be rearranged.
Also, if they were not volatile, when you say b=6 it may not happen right away. So if you check the value of c (given enough time for the hardware to respond) if c is not volatile you may read a local cached value of c and you might not see its NEW value. OR the hardware may change its copy of c and not update the global one. Or both could happen. Not to mention that the rearrangement of these commands can cause you to read c before a or b were assigned if it was not declared as volatile along with them.
Also ints are 32 bits. Processors today work in 64 bits, but lets just say you have an old one which works on 32 bits. Now examine this command
[code]
double x;
x = 1048560; /* 0x000FFFF0 in hex */
x = x + 5
[code]
Now since the processor works in 32 bits, it will load the first 2 bytes of data 0x000f and then the 2nd 0xfff0. Since this takes 2 steps, in between some other thread could come along and write a new value.
thread 1 reads high bytes 0x000f
thread 2 writes low bytes 0x0000
thread 1 reads low bytes 0x0000
thread 2 writes high bytes 0x0000
thread 1 writes value back + 1
since this operation was sliced in half, new value is
0x000f0001
Volatile variables will prevent anything from interrupting their operations. Their operations will be "atomic."

Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by marilyn murphy:
>4. If i am not wrong you have said that volatile make operations atomic

"volatile" does not make changes atomic. [...]
Seconded what CLG states above: this is incorrect. Section 17.4 of the language specification states that load, store, read, and write actions on volatile variables are atomic, even if the type of the variable is double or long.
Apart from atomicity, making a variable volatile guarantees that threads will always keep their idea of what the value of the variable is in sync with the actual value in memory, and will preserve the order of assignments and loads as stated in the source code. Without the volatile modifier or synchronization the JLS does not guarantee that/when modifications of a variable show up in other threads.
Formally, that means that quite a few applications and libraries have hard to detect bugs that might to show up under rare circumstances (particular JVMs, multi-processor machines). Having said that, seeing that this problem is present inside the Java libraries itself it is likely that JVMs won't exhibit the problem in practice (e.g. the Vector.elementCount private variable is not volatile, yet access is generally unsynchronized).
A minor remark, current x86 CPUs still have a 32-bit architecture (even though the data bus is wider).
- Peter
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

>4. If i am not wrong you have said that volatile make operations atomic

"volatile" does not make changes atomic. [...]
Seconded what CLG states above: this is incorrect. Section 17.4 of the language specification states that load, store, read, and write actions on volatile variables are atomic, even if the type of the variable is double or long.

Yes volatile does make operations on longs and doubles atomic whereas they are not ordinarily mandated to be. Its true that a load action is indivisible and thus atomic. But variables such as long and double may require 2 load actions since they are 64bits. In this case, volatile will make sure those 2 actions are not divided.
[This message has been edited by CL Gilbert (edited October 22, 2001).]
Peter Haggar
author
Ranch Hand

Joined: Jan 03, 2001
Posts: 106
Originally posted by CL Gilbert:
Yes volatile does make operations on longs and doubles atomic whereas they are not ordinarily mandated to be. Its true that a load action is indivisible and thus atomic. But variables such as long and double may require 2 load actions since they are 64bits. In this case, volatile will make sure those 2 actions are not divided.
[This message has been edited by CL Gilbert (edited October 22, 2001).]

This is how volatile is supposed to work for 64 bit variables (double and long) on a 32 bit machine. However, most JVMs don't implement volatile correctly for 64-bit variables. They wind up being non-atomic even if declared volatile. Therefore, you must use synchronization to ensure correct values in a multithreaded environment.
Peter Haggar
------------------
Senior Software Engineer, IBM
author of: Practical Java


Senior Software Engineer, IBM
author of: Practical Java
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Originally posted by Peter Haggar:
This is how volatile is supposed to work for 64 bit variables (double and long) on a 32 bit machine. However, most JVMs don't implement volatile correctly for 64-bit variables. They wind up being non-atomic even if declared volatile. Therefore, you must use synchronization to ensure correct values in a multithreaded environment.
Peter Haggar

Where did you get that information? In any event, I disagree with it. First of all most processors can already handle 64bits of data at once. Second, most operations on longs and doubles are already atomic since the 64bit data is handled atomicly. So even when you dont declare volatile chances are very high that the operations will be atomic anyway. I _highly_ doubt "most" if any JVMs would be violating the JLS or the JVM spec.
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by CL Gilbert:
Where did you get that information? In any event, I disagree with it.
Hmmmm. Peter Haggar is firmly in my "do homework before disagreeing" category. Let's see...
First of all most processors can already handle 64bits of data at once.
You mean they have wide databuses - which is irrelevant. The core x86 execution units (as opposed to the FP, MMX and SSE units) are still 32-bit. I suggest you read section 17.4. of the Java Language Specification: The model divides [long memory transfers] into 32-bit halves for the sake of several currently popular microprocessors that fail to provide efficient atomic memory transactions on 64-bit quantities. Also see The IA-32 Intel Architecture Software Developer´┐Żs Manual, Volume 2: Instruction Set Reference, chapter 3.2, MOVQ (Move Quadword): Copies a quadword from the source operand (second operand) to the destination operand (first operand). The source and destination operands can be MMX registers, XMM registers, or 64-bit memory locations. Note the absence of general-purpose register pairs as a possible source or destination. Ditto for the other instructions that might be used; I'm not going to quote all of them here.
I didn't know about the buggy JVM implementations. But I have no reason to doubt Peter's word.
- Peter

[This message has been edited by Peter den Haan (edited October 26, 2001).]
Peter Haggar
author
Ranch Hand

Joined: Jan 03, 2001
Posts: 106
Originally posted by CL Gilbert:
Where did you get that information?...So even when you dont declare volatile chances are very high that the operations will be atomic anyway.

Take a look at Bill Pugh's web page. There's a lot there about all kinds of problems with the memory model, but you want to look at AtomicLong.java. Here's a copy of the program which shows how volatile doesn't work on most VMs.

The only VM Bill found it works on is Solaris JDK 1.2.2. I've run it on IBM's 1.3, and Sun's 1.2 and 1.3. Fails on all. The code can be a little strange at first, but if you have questions about what's happening feel free to post. Also, this subject and the above code is part of an article I have coming out in a future issue of Dr. Dobb's. No publish date yet.
I _highly_ doubt "most" if any JVMs would be violating the JLS or the JVM spec.
I've got a bridge to sell you real cheap Seriously, I highly doubt there is one that doesn't in some way. There are other problems with volatile that haven't even been discussed here. For example, most VMs (none that Bill tested) honor its supposed guarantees of sequential consistency. He has a test program for that too. For example:

Running code like the above on multiple threads, stop can be set to true BEFORE num is set to 100. Volatile is supposed to ensure these statements don't get reordered. Again, most VMs don't implement this.
JSR-133, which Bill Pugh, Tim Lindholm, and others are on are is supposed to address these and other issues with the memory model.
I hope this clears it up.
Peter Haggar
------------------
Senior Software Engineer, IBM
author of: Practical Java
Brett Delia
Greenhorn

Joined: Feb 22, 2001
Posts: 20
Why not just syncronize on the variable in question? Would this not garuntee atomic behavior?
Peter Haggar
author
Ranch Hand

Joined: Jan 03, 2001
Posts: 106
Originally posted by Brett Delia:
Why not just syncronize on the variable in question? Would this not garuntee atomic behavior?

Yes it would. However, using synchronization limits the concurrency of your code. For 32-bit variables, you could declare them volatile and make them thread safe. However, this means that every time they are accessed their local copy is reconciled with main memory. They are more concurrent though.
If it's a 64-bit variable, you have, almost, no choice but to use synchrnoization, since volatile is not implemented correctly for 64-bit variables on most JVMs.
Peter Haggar

------------------
Senior Software Engineer, IBM
author of: Practical Java
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Originally posted by Peter den Haan:
You mean they have wide databuses - which is irrelevant. The core x86 execution units (as opposed to the FP, MMX and SSE units) are still 32-bit

Indeed the databus is irrelevant. So is the execution unit. The only relevant thing is that the software will see. So even if the processor breaks it down into 4 bit instructions, as long asn the end result is a single operation with respect to the software, its completely ok.
I still highly doubt most JVMs would be violating the spec. This does not mean I am wrong. It just means I doubt it and would be speechless if it were true.
In any event, the information I gave was correct. It also seems that the information I am receiving is correct. What I wrote is technically the proper way to write your code, but since there are violations, the things which have been pointed out to me sadly, must be respected...
[ February 26, 2002: Message edited by: CL Gilbert ]
Peter Haggar
author
Ranch Hand

Joined: Jan 03, 2001
Posts: 106
Originally posted by CL Gilbert:

I still highly doubt most JVMs would be violating the spec. This does not mean I am wrong. It just means I doubt it and would be speechless if it were true.

Then you obviously haven't read my post, or run the code I posted, or visited Bill Pugh's web site I linked, or looked at JSR-133. If you had, you would be speechless. Don't take my word for it, run the code. Bill also has a test program to show how sequential consistency is broken.

In any event, the information I gave was correct. It also seems that the information I am receiving is correct.

Your information about volatile was correct based on the spec, but incorrect based on how most VMs implement the spec. I am saying your code doesn't work because most VMs don't implement the spec properly wrt to volatile.


What I wrote is technically the proper way to write your code, but since there are violations, the things which have been pointed out to me sadly, must be respected...

Yes, technically proper based on the spec, but also technically broken based on VM implementations. The bottom line on volatile, on most VMs is this:
1) It is supposed to ensure sequential consistency, however, on most VMs it doesn't. Therefore, there is no guarantee that with multiple threads in the below code, num will be assigned before stop.

2) It is supposed to ensure that 64-bit variables are treated atomically. However, it doesn't on most VMs. volatile does not guarantee atomicity with regard to 64-bit variables on a 32-bit machine.
The bottom line to all this is not to rely on the specified behavior of volatile without testing your VM first. JSR-133 is revising the memory model to address these and other problems.
Peter Haggar
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by CL Gilbert:
Indeed the databus is irrelevant. So is the execution unit. The only relevant thing is that the software will see. So even if the processor breaks it down into 4 bit instructions, as long asn the end result is a single operation with respect to the software, its completely ok.
But it isn't. That was the entire point of my reply - x86 load/store instructions to/from general-purpose registers are all 32 bit, hence no atomicity, no "single operation with respect to the software".
- Peter
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Originally posted by Peter Haggar:

Running code like the above on multiple threads, stop can be set to true BEFORE num is set to 100. Volatile is supposed to ensure these statements don't get reordered. Again, most VMs don't implement this.

You do understand that the above code is not thread safe and in no way should guarantee order of access to variables on multiple threads? Within the same thread, yes, the order should be preserved, but between multiple threads, 1 thread could be accessing one variable while another is accessing another.
Volatile does not provide even a hint of thread safety.
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

I did run the atomicLong example on sun 1.3.1_03 and it did fail to properly handle the volatile variable.
Abominable.
That usage is really not that important anyway. Its next to useless. But its quite strange that they fail it. Maybe they thought as I do and got lazy. Im checking on the Order of execution example too see what I can make of it...
[ July 12, 2002: Message edited by: CL Gilbert ]
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Good news.
AtomicLong runs ok under jsdk 1.4.0_01 in WNT
Still the following code prints something. And I cannot figure out why.

Maybe the answer was given by Doug Lea on page 97 from Concurrent Programming in Java:

Using volatile fields can make sense when it is somehow known that only one thread can change a field, but many others are allowed to read it at any time.

_______________________________________
I agree compilers or VMs don't comply with JLS 100% . You can find some discrepancies in the Bug Database in Sun.
[ September 16, 2002: Message edited by: Jose Botella ]

SCJP2. Please Indent your code using UBB Code
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
Originally posted by Jose Botella:
AtomicLong runs ok under jsdk 1.4.0_01 in WNT

Runs fine under Win2000 jsdk1.4.1


Associate Instructor - Hofstra University
Amazon Top 750 reviewer - Blog - Unresolved References - Book Review Blog
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056
AtomicLong fails on Java 1.3.1 running on Mac OS X 10.2 (Jaguar).


Ron Newman - SCJP 1.2 (100%, 7 August 2002)
Mr. C Lamont Gilbert
Ranch Hand

Joined: Oct 05, 2001
Posts: 1170

Originally posted by Peter den Haan:
But it isn't. That was the entire point of my reply - x86 load/store instructions to/from general-purpose registers are all 32 bit, hence no atomicity, no "single operation with respect to the software".
- Peter

Just because the CPU does not do it atomically does not mean the software can not present it as an atomic operation. The JVM can create the atomicity here and that is what it is supposed to do. Else a java program would be different based on which CPU its run on, and that is contrary to the stated mission of Java (though it still seems to be the case to some degree.)
Pin Ting
Greenhorn

Joined: May 28, 2003
Posts: 22
Originally posted by Jose Botella:
Good news.
AtomicLong runs ok under jsdk 1.4.0_01 in WNT
Still the following code prints something. And I cannot figure out why.

Maybe the answer was given by Doug Lea on page 97 from Concurrent Programming in Java:

_______________________________________
I agree compilers or VMs don't comply with JLS 100% . You can find some discrepancies in the Bug Database in Sun.
[ September 16, 2002: Message edited by: Jose Botella ]

the code doesn't compile due to this line:
testValue1 = testVariable;
what's the correct variable name?


Never do things the hard way if you don't have a good reason.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Behaviour of Volatile variables