Preface
volatile
is a keyword in Java that is used to modify variables. It provides the characteristics of visibility and prohibiting instruction rearrangement, but does not guarantee atomicity.
1. Visibility
- Question background:In a multi-threaded environment, each thread has its own working memory (such as CPU cache). The thread's read and write operations on shared variables may not be performed directly in the main memory, but in the working memory. This may cause one thread to modify the value of the shared variable, while other threads cannot see the modification, thus reading the expired value.
-
The role of volatile :When a variable is
volatile
When modified, it guarantees:-
Write operation:When a thread is modified
volatile
The value of the variable, this new value will be immediately refreshed to the main memory. -
Reading operation:When a thread reads
volatile
When a variable is used, it will read the latest value from the main memory, rather than from its own working memory.
-
Write operation:When a thread is modified
-
Implementation principle:
volatile
Visibility is achieved through the Memory Barrier. A memory barrier is a CPU instruction that prevents the compiler and CPU from reordering the instructions and force data from working memory to or read from main memory.
Code example:
public class VolatileVisibilityExample { private static volatile boolean flag = false; // private static boolean flag = false; If volatile is not used, thread 1 may not be stopped public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { while (!flag) { // ... (Cycle to perform certain operations) ... } ("Thread 1 stopped."); }); Thread thread2 = new Thread(() -> { try { (1000); // Let thread1 execute first } catch (InterruptedException e) { (); } flag = true; // Modify the value of flag ("Thread 2 set flag to true."); }); (); (); } }
2. Prohibit Ordering
- Question background:To optimize performance, the compiler and CPU may reorder the execution order of instructions as long as it does not affect the execution results of a single-threaded program. However, in a multi-threaded environment, instruction reordering may cause unexpected behavior in the program.
-
The role of volatile :
volatile
Keywords can prohibit specific types of instructions to reorder:-
Read after writing:Can't be put
volatile
The write operation of variables is rearranged after the read operation. -
Write after writing:Can't be put
volatile
The write operation of a variable is rearranged to anothervolatile
After the variable write operation. -
Read/write after reading:Can't be transferred
volatile
Reading of variables is rearranged to anothervolatile
After the read or write operation of the variable.
-
Read after writing:Can't be put
-
Implementation principle:
volatile
Shield command reflow is prohibited by inserting a specific type of memory barrier. For example, involatile
After the write operation of the variable, a StoreStore barrier will be inserted, and before the read operation, a LoadLoad barrier will be inserted, and a possible StoreLoad barrier will be inserted. -
Example of Double-Checked Locking:
volatile
Often used for double checking lock mode to prevent problems caused by instruction reordering.//Singleton Modepublic class Singleton{ //Use volatile to prohibit the instruction reordering of instance = new Singleton() private static volatile Singleton instance; private Singleton(){} public static Singleton getInstance(){ if(instance == null){ //First check synchronized(){ if(instance == null){ //The second check prevents multiple threads from passing the first check at the same time instance = new Singleton(); } } } return instance; } }
3. Atomicity is not guaranteed
-
Important Note:
volatile
The atomicity of the operation is not guaranteed. Atomicity refers to an operation that is indivisible, either executed in all or not, and there will be no execution. -
example:
volatile
Self-increase operation of variables (i++
) is not atomic. It actually consists of three steps: Readi
The value of willi
Add the value of 1. Write the new value backi
. In a multi-threaded environment, these three steps may be interrupted by other threads, resulting in an error in the result. - **Solution: **If you need to ensure atomicity, you can use
synchronized
、ReentrantLock
or atomic class (such asAtomicInteger
)。
Summarize:
-
volatile
Keywords are used to modify variables, provide visibility and prohibit instruction rearrangement. - Visibility guarantee thread pair
volatile
The read and write operations of variables are performed directly in the main memory. - Prohibit instruction re-arrangement to prevent compiler and CPU from matching
volatile
Reorder variable-related instructions. -
volatile
Atomicity is not guaranteed. -
volatile
Usually used in scenarios such as status flags, double check locking, etc.
Problem analysis:
This question has been examined correctlyvolatile
Understanding keywords includes its role, characteristics (visibility, prohibited instruction rearrangement) and limitations (not guaranteed atomicity). These concepts need to be explained clearly when answering, and some code examples are provided to illustrate the problem.
Contact knowledge points on other questions:
-
What is Java Memory Model (JMM)?
volatile
is part of the Java Memory Model (JMM), which defines the interaction rules between threads and main memory. -
What are atomicity, visibility and order in Java?
volatile
Visibility and orderliness are provided (instruction rearrangement is prohibited), but atomicity is not guaranteed. -
What are the happens-before rules for Java?
volatile
Write operation of variable happens-before The subsequent read operation of the variable. -
What is instruction reordering in Java?
volatile
Specific types of instructions can be prohibited from re-arrangement. -
How is synchronized implemented in Java?
synchronized
Provides atomicity, visibility and orderliness. In some cases,volatile
Can be used assynchronized
A lightweight alternative to (if only visibility and orderliness are required). -
Which atomic classes have you used in Java?Atomic class (such as
AtomicInteger
) provides atomic operations that can be used instead ofvolatile
+ Extra synchronization scheme. - Can the final keyword in Java ensure the visibility of variables?Final keywords can ensure visibility.
Understanding these connections can help you gain a more comprehensive understanding of Java concurrent programming and understand how to choose the right synchronization mechanism in practical applications.
This is the end of this article about what the role of volatile keywords in Java. For more related content of Java volatile keywords, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!