当前位置:网站首页>Volatile and JMM
Volatile and JMM
2022-06-27 14:35:00 【It takes time for fish to find water】
By volatile Decorated variables have two characteristics
visibility
After finish Flush back to main memory immediately and in time A notice , You can go to the main memory to get the latest version , The previous changes are visible to all subsequent threads
Orderliness
There is no data dependency , You can reorder
There is a data dependency , No reordering
But the rearranged instructions can never change the original serial semantics ! This must be taken into account in concurrent design !
When you write a volatile variable ,JMM The shared variable value in the local memory corresponding to the thread will be Flush back to main memory now in
When reading a volatile variable ,JMM Will set the local memory corresponding to this thread to be invalid , Read the latest shared variable in main memory again
therefore volatile The write memory semantics of is to refresh directly into main memory , The memory semantics of reading is to read directly from main memory
volatile Why visibility and order can be guaranteed
Memory barrier Memory Barrier
Memory barrier ( Also become a memory fence , Barrier order, etc , Is a kind of synchronous barrier instruction , yes CPU Or a synchronization point in the compiler's operation on random access to memory , Only after all the read and write operations before this point are executed can the operations after this point be started ), Avoid code reordering . Memory barrier is actually a kind of JVM Instructions ,Java The memory model rearrangement rules will requirement Java The compiler is generating JVM Insert a specific memory barrier instruction , Through these your memory barrier instructions ,volatile Realized Java Visibility and ordering in the memory model ( No rearrangement ), but volatile There is no guarantee of atomicity .
Before the memory barrier All of the Write operations Both Write back to main memory
Behind the memory barrier All of the Read operations Can get the latest results of all write operations before the memory barrier ( Visibility is achieved )
Write barriers (Store Memory Barrier) : Tell the processor to store all in the cache before writing the barrier (store bufferes) Data in is synchronized to main memory . That is, when you see Store Barrier directive , You must execute all the write instructions before the instruction before continuing to execute .
Reading barrier (Load Memory Barrier) : The read operation of the processor behind the read barrier , After reading the barrier . That is to say Load After the barrier instruction, it can ensure that the subsequent read data instruction can read the latest data .

So when reordering , It is not allowed to reorder the instructions after the memory barrier to the instructions before the memory barrier . In a word : To a volatile Variable writing , The antecedent happens to any subsequent pair of this volatile Variable reading , Also called reading after writing
Roughly divided into 2 Kind of
Reading barrier (Load Barrier): Insert a read barrier before reading instructions , Let working memory or CPU The cached data in the cache is invalid , Go back to main memory to get the latest data
Write barriers (Store Barrier): Insert a write barrier after writing instructions , Force data written to the buffer to be flushed back to main memory
| First action | Second operation : Ordinary reading and writing | Second operation :volatile read | Second operation :volatile Write |
|---|---|---|---|
| Ordinary reading and writing | You can rearrange | You can rearrange | You can't rearrange |
| volatitle read | You can't rearrange | You can't rearrange | You can't rearrange |
| volatitle Write | You can rearrange | You can't rearrange | You can't rearrange |
When the first act volatile Reading time , Whatever the second operation is , Can't reorder . This operation ensures that volatile After reading Operations of will not be rescheduled to volatile Before reading .
When the second drill does volatile Writing time , Whatever the first operation is , Can't reorder . This operation ensures that volatile Before writing Operations of will not be rescheduled to volatile After writing .
When the first act volatile Writing time , The second act volatile Reading time , Can't rearrange
Reading barrier : At every volatile Insert a... After the read operation LoadLoad barrier , Insert a after each read operation LoadStore barrier

Write barriers : At every volatile Insert a... After the write operation StoreStore barrier , Insert one after each inverted error StroeLoad barrier

JMM The memory barrier insertion strategy is divided into 4 Rules in

volatile characteristic
explain : Ensure that the results of different threads' operations on a variable are visible in time , That is, once the shared variable is changed, all threads are immediately visible .
Guaranteed visibility
Example
//static boolean flag = true;
static volatile boolean flag = true;
public static void main(String[] args)
{
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+"\t -----come in");
while(flag)
{
}
System.out.println(Thread.currentThread().getName()+"\t -----flag Set to false, The program to stop ");
},"t1").start();
// Pause the thread for a few seconds
try {
TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) {
e.printStackTrace(); }
flag = false;
System.out.println(Thread.currentThread().getName()+"\t Modified to complete flag: "+flag);
}
The above code : No addition volatile, No visibility , The program cannot stop
added volatile, Guaranteed visibility , The program can stop
The problem that the program cannot stop may be :
- The main thread has changed flag After that, it is not flushed to main memory , therefore t1 Threads can't see
- The main thread will flag Flushed to main memory , however t1 Always read from your working memory flag Value , There is no update in main memory to get flag The latest value ( Self working memory is private to each thread , Main memory is shared memory )
Desired results :
- After the thread modifies the copy in its working memory , Immediately flush it to main memory
- Every time a working variable is read in the working memory , Go to the main memory and read again , Then copy to working memory
solve :
Use volatile Decorate shared variables , You can achieve the above effect , By volatile The modified variables have the following characteristics :
- In the thread Read When , Each read will read the latest value of the shared variable in the main memory , Then copy it to working memory
- In the thread modify Copies of variables in working memory , It will be flushed to main memory immediately after modification
Java As defined in the memory model 8 Kind of Each thread has its own working memory And Between main physical memory Atomic operation of
read( Read )→load( load )→use( Use )→assign( assignment )→stroe( Storage )→write( write in )→lock( lock )→unlock( Unlock )

read: For main memory , Transfer the value of the variable from main memory to working memory , Main memory to working memory
load: Working memory , take read The variable values transferred from the main memory are put into the work Memory variable copy in , That is, data loading
use: Working memory , Pass the value of the working memory variable copy to the execution engine , whenever JVM This operation is performed when a bytecode instruction that requires the variable is encountered
assign: Working memory , Assign the value received from the execution engine to the working memory variable , whenever JVM This operation is performed when a bytecode instruction assigned to a variable is encountered
store: Working memory , Write the value of the assigned working variable back to the main memory
write: For main memory , take store The transferred variable value is assigned to the variable in main memory
Because of the above 6 One instruction can only guarantee the atomicity of a single instruction , Combinatorial atomic guarantee for multiple instructions , No large area locking , therefore ,JVM Two other atomic instructions are provided
lock: For main memory , Mark a variable as a thread exclusive state , Just lock it when writing , Just lock the process of writing variables
unlock: For main memory , Release a locked variable , Then it can be occupied by other threads
There is no atomicity
class MyNumber
{
volatile int number;
public void addPlusPlus() //synchronized
{
number++;
}
}
public class VolatileNoAtomicDemo
{
public static void main(String[] args)
{
MyNumber myNumber = new MyNumber();
for (int i = 1; i <=10; i++) {
new Thread(() -> {
for (int j = 1; j <=1000; j++) {
myNumber.addPlusPlus();
}
},String.valueOf(i)).start();
}
// Pause the thread for a few seconds
try {
TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) {
e.printStackTrace(); }
System.out.println(myNumber.number); // The correct result should be :10000, The actual output is not
}
}

Without a lock , When a thread 1 Initiate... For main memory objects read Operate to write The time to operate the first set of processes , Threads 2 It is possible at any time for this Main memory object Initiate the second set of operations


about volatile Variables have visibility ,JVM Just make sure that the value loaded from main memory to thread working memory is new , It is only new when the data is loaded . But in a multithreaded environment ,” Data calculation “ and ” Data assignment “ The operation may occur more than once , If the data is loaded , If main memory volatile After the modification of modification variables , The operation in the thread working memory will be invalidated to read the latest value in the main memory ( It has visibility ), Write loss occurred during operation , namely The variables in the private memory and the public memory of each thread are not synchronized , This leads to inconsistent data . thus it can be seen volatile The solution is the visibility problem of variable reading , But atomicity is not guaranteed , Locking synchronization must be used in the scenario of multi-threaded modification of main memory shared variables .
Atomicity means that an operation is Non interruptible Of , Even in a multithreaded environment , Once an operation is started, it will not be affected by other threads .
public void add(){
i++; // It's not atomic , The operation is to read the value first , Then write back a new value , Equivalent to the original value plus 1, branch 3 Step through
}
If the second thread reads between the first thread reading the old value and writing back the new value i The domain value of , Then the second thread will see the same value as the first thread , And add the same value 1 operation , This creates thread safety issues , So for add Method must use synchronzed Decorate to ensure thread safety .
volatile Variables are not suitable for operations that depend on the current value
Instruction no rearrangement
Reordering is a means by which compiler and processor reorder instruction sequences in order to optimize program performance , Sometimes it will change the sequence of program statements , There is no data dependency , You can reorder
There is a data dependency , No reordering
But the instruction after the remake must not change the original serial semantics ! This must be taken into account in concurrent design !
Sorting and execution process of reordering

Data dependency : If two operations access the same variable , And one of these two operations is write operation , At this time, there is data dependency between the two operations .
| Before rearranging | After rearranging |
|---|---|
| int a = 1; // The first sentence int b = 2; // The second sentence int c = a + b; //3 | int b = 2; // The first sentence int a = 1; // The second sentence int c = a + b; //3 |
| Conclusion : Suppose the compiler adjusts the order of statements , But it doesn't affect the end result of the program . | Reorder OK |
The following example : If there is a data dependency , No reordering . After reordering occurs , Will cause the program to run differently
| - | Code | explain |
|---|---|---|
| Read after writing | a = 1; b = a; | After writing a variable , Read this variable again |
| Write after | a = 1; a = 2; | After writing a variable , Write this variable again |
| After reading | a = b; b = 1; | After reading a variable , Write this variable again |
volatile Use... Correctly
A single assignment can , But the assignment with compound operation cannot (i++ And so on )
// Single assignment volatile int a = 10; volatile boolean flag = false;Status flag : Determine whether the business is over
private volatile static boolean flag = true;
public static void main(String[] args) {
new Thread(()->{
while (flag){
//do something
}
},"t1").start();;
try {
Thread.sleep(2L);} catch (InterruptedException e) {
throw new RuntimeException(e);}
new Thread(()->{
flag = false;
},"t2").start();;
}
Low cost reading , Write lock strategy
/** * Use : When reading is far more than writing , Use a combination of internal locks and volatile Variable to reduce the overhead of synchronization * reason : utilize volatile Ensure the visibility of the read operation , utilize synchronized Ensure the atomicity of composite operation */ public class Counter{ private volatile int value; public int getValue(){ return value; // utilize volatile Ensure the visibility of the read operation } public synchronized int intcrement(){ return value++; // utilize synchronized Ensure the atomicity of composite operation } }DCL Release of double end lock (double-checked-locking)
Singleton mode in multithreading

volatile summary
1)volatile visibility
2)volatile There is no atomicity
3)volatile No rearrangement
4)volatile Add memory barrier at the bottom of keyword system , How the two are related
5) What is the memory barrier
6) Memory barrier function
7) Memory barrier four instructions
3 Sentence summary
1)volatile The operation before writing , It is forbidden to reorder to volatile after
2)volatile Operation after reading , It is forbidden to reorder to volatile Before
3)volatile After writing volatile read , No reordering
边栏推荐
- 隱私計算FATE-離線預測
- 巧用redis实现点赞功能,它不比mysql香吗?
- Use GCC to generate an abstract syntax tree "ast" and dump it to Dot file and visualization
- 机械硬盘和ssd固态硬盘的原理对比分析
- Leetcode 724. Find the central subscript of the array (yes, once)
- Massive data! Second level analysis! Flink+doris build a real-time data warehouse scheme
- 522. longest special sequence II / Sword finger offer II 101 Split equal sum subset
- 线程同步之信号量
- [PHP code injection] common injectable functions of PHP language and utilization examples of PHP code injection vulnerabilities
- How to solve the problem of missing language bar in win10 system
猜你喜欢

初识云原生安全:云时代的最佳保障

跨境电商多商户系统怎么选

NAACL 2022 | TAMT:通过下游任务无关掩码训练搜索可迁移的BERT子网络

Practice of constructing ten billion relationship knowledge map based on Nebula graph

Learning records of numpy Library
机械硬盘和ssd固态硬盘的原理对比分析

直播app运营模式有哪几种,我们该选择什么样的模式?

清华&商汤&上海AI&CUHK提出Siamese Image Modeling,兼具linear probing和密集预测性能!...

Great God developed the new H5 version of arXiv, saying goodbye to formula typography errors in one step, and the mobile phone can easily read literature

隐私计算FATE-离线预测
随机推荐
初识云原生安全:云时代的最佳保障
事务的四大特性
What if the win system cannot complete the update and is revoking the status change
AQS抽象队列同步器
清华&商汤&上海AI&CUHK提出Siamese Image Modeling,兼具linear probing和密集预测性能!...
The global chip market may stagnate, and China's chip expansion accelerates to improve its self-sufficiency rate against the trend
Leetcode 724. 寻找数组的中心下标(可以,一次过)
Redis persistence
How to set the compatibility mode of 360 speed browser
NLP - monocleaner
[an Xun cup 2019]attack
In the past, domestic mobile phones were arrogant in pricing and threatened that consumers would like to buy or not, but now they have plummeted by 2000 for sale
Unity3d best practices: folder structure and source control
Kyndryl与Oracle和Veritas达成合作
Design and implementation of reading app based on Web Platform
OpenSSF安全计划:SBOM将驱动软件供应链安全
Use GCC to generate an abstract syntax tree "ast" and dump it to Dot file and visualization
ReentrantLock、ReentrantReadWriteLock、StampedLock
Brief reading of dynamic networks and conditional computing papers and code collection
Nvidia Deepstream 运行延迟,卡顿,死机处理办法