当前位置:网站首页>Volatile keyword of JVM memory model
Volatile keyword of JVM memory model
2022-07-26 19:29:00 【a_ ittle_ pan】
Start writing
“ If you don't eat, you will be hungry , If you don't read, you'll be stupid ”

Reference books :“ In depth understanding of java virtual machine ”
about volatile Special rules for type variables
The book follows , The previous article learned that java The origin of memory model 、 Interaction between main memory and working memory , In this article, let's take a look at the memory model for Volatile Memory definition of keywords .
private static volatile SingleInstance singleInstance = null;
public static SingleInstance getSingleInstance(){
if (singleInstance == null) {
synchronized (SingleInstance.class) {
if (singleInstance == null) {
singleInstance = new SingleInstance();
}
}
}
return singleInstance;
}
I don't know about the DCL( Double check ) Is this writing still impressive , This kind of writing is used Volatile Keyword to modify variables , As for why to use Volatile Keywords to modify , Please finish reading this article .
visibility
When a variable is defined as Volatile after , It will have two characteristics , The first is to ensure the visibility of this variable to all threads , there “ visibility ” When a thread changes the value of this variable , The new value is immediately known to other threads . And ordinary variables can't do that , The values of common variables need to be passed through main memory , for example , Threads A Change the value of a common variable , Then write back to main memory , Another thread B In a thread A After the write back is completed, read from the main memory , The value of the new variable will be on the thread B so , The whole process is a thread A To thread B Sent a message “ I changed the value of the variable ”( One of the ways of communication between threads ).
although Volatile Ensure the visibility of data , But it does not mean thread safety of data , Let's use a case to verify :
public class VolatileTest {
public static volatile int race = 0;
private static final int THREADS_COUNTS = 20;
public static void increase() {
race++;
}
public static void main(String[] args) throws InterruptedException {
Thread[] threads = new Thread[THREADS_COUNTS];
for (int i = 0; i < THREADS_COUNTS; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < 10000; j++) {
increase();
}
});
threads[i].start();
}
Thread.sleep(20000);
System.out.println("race = "+race);
System.out.println("ThreadActiveCount = "+Thread.activeCount());
}
}

If race It's thread safe , So the returned result should be 200000, But through practical verification, it is found that it is a ratio 200000 Small number , What caused the inconsistent results ?
The problem is in the self increasing operation “race++” In , use Javap After decompiling this code, it is found that there is only one line of code increase() Method in Class In the document is by 4 Made up of bytecode instructions (return The order was not given by race++ Produced , This command can be ignored ), From the bytecode level, it is easy to analyze the concurrency loss The reason for the defeat : When getstatic Give orders to race When the value of is taken to the top of the operation stack ,volatile Keywords guarantee race The value of is correct at this time , But in execution iconst_1、iadd When these instructions , Other threads may have put race The value of , And the value at the top of the operation stack becomes expired data , therefore putstatic After the instruction is executed, the smaller race value Sync back to main memory .
To sum up, it is :volatile There is no consistency between variables in the working memory of each thread ( In the working memory of each thread ,volatile Variables can also have inconsistencies , But since you need to refresh before each use , The execution engine doesn't see inconsistencies , Therefore, it can be considered that there is no problem of consistency ), however Java The operations inside are not atomic operations , Lead to volatile The operation of variables is also unsafe under concurrency .
Although I say Volatile Only ensure order 、 visibility , However, thread safety can be guaranteed as long as the following two rules are met :
- The result of the operation does not depend on the current value of the variable , Or make sure that only a single thread changes the value of the variable
- Variables do not need to participate in invariant constraints with other state variables .
Explain these two rules through a case :
volatile boolean shutdownflag = false;
public void shutdown(){
shutdownflag = true;
}
public void dowork(){
while(!shutdownflag){
//dosomething
}
}
It is not difficult for us to observe this case ,shutdownflag Did not participate in the specific logical operation , It is only used as a judgment condition , When a thread calls shutdown Method time , Can guarantee dowork All the execution threads of stop immediately .
Orderliness
Use volatile The second semantics of variables is to prohibit the reordering optimization of instructions , Ordinary variables are only guaranteed in this method The correct results can be obtained in all places that depend on the assignment results during the execution of , It can't guarantee that the order of variable assignment operation is consistent with the execution order in the program code . Because in the process of a thread's method execution, we can't perceive this , This is the same. Java The so-called... Described in the memory model “ The semantics within a thread are expressed as serial ”(Within-Thread As-If-Serial Semantics)
Or an explanation through a case :
public class VolatileTest2 {
private static VolatileTest2 singletonInstance;
public static VolatileTest2 getVolatileTest2() {
if (singletonInstance == null) {
synchronized (VolatileTest2.class) {
if (singletonInstance == null) {
singletonInstance = new VolatileTest2();
}
}
}
return singletonInstance;
}
}
This is an irregular DCL How to write it , This writing method has some defects , Users may get an instantiation that is not complete VolatileTest2 object . The normal logic is when A The thread passes for the first time getVolatileTest2() Method to get an object at this time singletonInstance still null value , It will be right at this time singletonInstance instantiate , Then return the instantiated object to the caller , But the actual effect may not be like this , Due to the optimization strategy of the compiler or hardware, it will reorder these instructions , That means singletonInstance The process of instantiation operation may return after optimization singletonInstance Execute after this statement , So it will cause users to get singletonInstance An object is an object with incomplete instantiation or null object .
and Volatile It is through the memory barrier to ensure the order of instructions , If you are interested, you can go to Du Niang , It's worth studying .
Let's look back Java In the memory model volatile Special rules for variable definition . Assume T Represents a thread ,V and W Two... Respectively volatile Type variable , So it's going on read、load、use、assign、 store and write The following rules shall be met during operation :
- Only when the thread T The variable V The previous action is load When , Threads T To the variables V perform use action ; also , Only when the thread T The variable V The next action to perform is use When , Threads T To the variables V perform load action . Threads T The variable V Of use Actions can be thought of as and threads T The variable V Of load、read Actions are related , Must appear together in succession ( This rule requires that in working memory , Each use V You must first refresh the latest value from main memory , Used to ensure that you can see other thread to variable V The modified value )
- Only when the thread T The variable V The previous action is assign When , Threads T To the variables V perform store dynamic do ; also , Only when the thread T The variable V The next action to perform is store When , Threads T To the variables V perform assign action . Threads T The variable V Of assign Actions can be thought of as and threads T The variable V Of store、write Actions are related , Must appear together in succession ( This rule requires that in working memory , Each modification V It must be synchronized back to main memory immediately , Used to ensure that other threads can see their own variables V Modifications made ).
- Suppose the action A Is the thread T The variable V Implemented use or assign action , Suppose the action F It's about action and movement A The associated load or store action , Suppose the action P It's about action and movement F The corresponding pair of variables V Of read or write action ; Allied , Suppose the action B yes Threads T The variable W Implemented use or assign action , Suppose the action G It's about action and movement B The associated load or store action , Suppose the action Q It's about action and movement G The corresponding pair of variables W Of read or write action . If A Precede B, that P Precede Q( This rule Requirements volatile Modified variables are not optimized by instruction reordering , Ensure that the code is executed in the same order as the program ).
One last word , because volatile Variables can only guarantee visibility and order , In some cases , We still have to lock ( Use synchronized or java.util.concurrent The atomic class in ) To ensure atomicity to achieve thread safety .
边栏推荐
- J2 Redis之 AOF&RDB
- Don't casually pass the request to the asynchronous thread. You can't handle it. You have to use the startasync method
- After the exam on June 25, see how the new exam outline reviews PMP
- 【YOLOv5】--详细版训练自己的数据集 保姆级学习日志记录 手把手教程
- Leetcode notes: biweekly contest 83
- C # get local time / system time
- How to solve the problem that win11 has been switched on after upgrading
- Introduction to Seata
- Write a starter
- C语言-入门-语法-字符串(十一)
猜你喜欢
随机推荐
EN 1504-6混凝土结构保护和修理用产品钢筋锚固—CE认证
如何保护电子商务网站免受网络攻击?
SEO、客户端渲染‘、服务端渲染、搜索引擎的理解
EN 1504-7混凝土结构保护和修理用产品钢筋防腐—CE认证
Support proxy direct connection to Oracle database, jumpserver fortress v2.24.0 release
Leetcode notes: biweekly contest 83
Sre person in charge of station B personally describes the multi activity disaster recovery construction after the 713 accident | takintalks share
C#创建及读取DAT文件案例
利用MySQL主从复制延迟拯救误删数据
Without Lin benjian, there would be no TSMC today!
TypeScript阶段学习
How many pairs can an array of leetcode simple questions form
[C language implementation] - dynamic / file / static address book
最后一篇博客
微信小程序插件--wxml-to-canvas(生成图片)
I'm cool, so I'm here
节约gas-ChiToken的用法
机器学习笔记 - 构建推荐系统(6) 用于协同过滤的 6 种自动编码器
Cannot find current proxy: Set ‘exposeProxy‘ property on Advised to ‘true‘ to make it available
The passwords are consistent, and the total display is as shown in the figure below
![[server data recovery] data recovery case of server storage shared folder loss](/img/bf/3f86a4e8abd4e045b022fd7574636f.png)








