NOTE
6.3 3.volatile
What volatile is, when it is more suitable than synchronized, an assembly experiment, and visibility/ordering analysis.
This is a historical learning note and may contain outdated or incomplete understanding.
1. What Is It?
A lightweight synchronization mechanism in Java. It mainly guarantees ordering, visibility, and atomic reads/writes of the variable itself.
- Lightweight
Compared withsynchronized,volatiledoes not itself cause threads to block. - Atomicity
Reads and writes of a singlevolatilevariable are atomic, but compound operations such asvolatileVar++are not atomic. - Visibility
A volatile write makes the update visible according to the Java Memory Model so that other threads subsequently reading the volatile variable can observe the latest write. - Ordering
A read of a volatile variable observes a write ordered before it according to the volatile happens-before rule.
2. When Is volatile More Suitable Than synchronized?
2.1. Example
In the following program, thread1 may not stop when isRunning is an ordinary non-volatile field.
public class VolatileTest
{
private static boolean isRunning = true;
public static void main(String[] args) throws InterruptedException
{
Thread thread1 = new Thread(()->{
System.out.println("thread1 is running");
while (isRunning)
{
}
System.out.println("thread1 will be stopped");
});
thread1.start();
Thread.sleep(1000);
Thread thread2 = new Thread(()->{
System.out.println("thread2 is running");
isRunning = false;
System.out.println("thread2 change isRunning flag");
});
thread2.start();
thread1.join();
thread2.join();
}
}
2.2. Analysis of Why It May Not Stop

The original note explains it conceptually as follows:
- Thread1 reads
isRunningand may continue using a value from its working-memory view. - Thread2 changes
isRunningfrom true to false. - Without a visibility guarantee, Thread1 is not guaranteed to observe Thread2’s update in the required way.
2.3. Solution
Declare isRunning as volatile.
public class VolatileTest
{
private static volatile boolean isRunning = true;
public static void main(String[] args) throws InterruptedException
{
Thread thread1 = new Thread(()->{
System.out.println("thread1 is running");
while (isRunning)
{
}
System.out.println("thread1 will be stopped");
});
thread1.start();
Thread.sleep(1000);
Thread thread2 = new Thread(()->{
System.out.println("thread2 is running");
isRunning = false;
System.out.println("thread2 change isRunning flag");
});
thread2.start();
thread1.join();
thread2.join();
}
}
2.4. volatile vs. synchronized
| volatile | synchronized | |
|---|---|---|
| Memory-model properties | Visibility, ordering, atomic read/write of the volatile variable itself | Visibility, ordering, and mutual exclusion for the protected critical section |
| Causes thread blocking | No by itself | May block |
| Scope | Variable level | Critical sections, methods, class-level locking |
3. Assembly-Code Experiment
3.1. Download and Compile hsdis-amd64.dll
Refer to How to build hsdis-amd64.dll and hsdis-i386.dll on Windows or hsdis-amd64.7z.
3.2. Put It in the JRE bin Directory

3.3. Comparison Experiment
- With volatile
public class TestVolatile
{
private static volatile int i = 0;
public static void main(String[] args)
{
test();
}
private static void test()
{
i++;
}
}
- Without volatile
public class TestVolatile
{
private static int i = 0;
public static void main(String[] args)
{
test();
}
private static void test()
{
i++;
}
}
3.4. Run with JVM Parameters
-server -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:-Inline -XX:CompileCommand=print,*TestVolatile.test
In IDEA:

3.5. Compare the Output
The results are in the attachments:
A Beyond Compare screenshot is shown below:

4. Analyze the Principle from the Experimental Result
At the assembly level, the volatile version has an additional instruction compared with the ordinary version: lock addl $0x0,(%rsp). In this experiment, it acts as a memory-barrier effect.
- Prevent relevant instructions on the two sides of the barrier from being reordered across it.
- Ensure the required visibility/ordering effects between the processor/cache subsystem and memory according to the platform and JVM implementation.
4.1. Visibility
The volatile memory-ordering semantics provide visibility:
- a volatile write publishes prior writes;
- another thread’s subsequent volatile read can observe the write and the preceding effects according to happens-before.
4.2. Ordering
The memory-ordering semantics also provide ordering.

Conceptually, a release barrier before a volatile write prevents earlier reads/writes from being reordered after the volatile write, while an acquire barrier after a volatile read prevents later reads/writes from being reordered before the volatile read.
5. References
- In-Depth Understanding of the Java Memory Model (4): volatile - InfoQ
- If Someone Asks You What volatile Is Again, Send Them This Article - HollisChuang’s Blog
- Underlying Implementation Principle of the Java volatile Keyword - Crow’s Blog
- Precisely Explaining Java volatile Visibility, Atomicity, and Ordering Through Assembly - OSCHINA
- Difference Between volatile and synchronized - Juejin
Discussion
Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub