In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article focuses on "how to achieve volatile memory visible", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "how to make volatile visible in memory".
Volatile explanation 1. Visibility case public class ApiTest {
Public static void main (String [] args) {
Final VT vt = new VT ()
Thread Thread01 = new Thread (vt)
Thread Thread02 = new Thread (new Runnable () {
Public void run () {
Try {
Thread.sleep (3000)
} catch (InterruptedException ignore) {
}
Vt.sign = true
System.out.println ("vt.sign = true notifies while (! sign) to end!")
}
});
Thread01.start ()
Thread02.start ()
}
}
Class VT implements Runnable {
Public boolean sign = false
Public void run () {
While (! sign) {
}
System.out.println ("you bad")
}
}
"this code" is two threads operating on a variable, and the program expects sign to output you bad when thread Thread01 is manipulated vt.sign = true.
But in fact, this code will never output you bad, but always in an endless loop. Why is that? Next, we will explain and verify it step by step.
two。 Add the volatile keyword
Let's add the volatitle description to the sign keyword, as follows:
Class VT implements Runnable {
Public volatile boolean sign = false
Public void run () {
While (! sign) {
}
System.out.println ("you bad")
}
}
"Test results"
Vt.sign = true notifies while (! sign) to end!
You're bad.
Process finished with exit code 0
The volatile keyword is the lightest synchronization mechanism provided by the Java virtual machine. It appears as a modifier to modify variables, but local variables are not included here.
After adding the volatile keyword, the program will output your bad as expected. We can know from our knowledge of volatile. The volatile keyword is the lightest synchronization mechanism provided by JVM, which is used to modify variables and to ensure that variables are visible to all threads.
After being modified, you can make the field visible to the thread, so after the value of this property is modified, you can respond in time in another thread.
3. How to ensure the visibility of volatile 3.1 when there is no volatile, the memory changes when there is no volatile.
The first is that when sign has no volatitle modification, thread 01 public boolean sign = false;, operates on the variable, and thread 02 does not get the changed value. So the program won't output the result "you're bad."
3.2 when there is volatile, the memory changes when there is volatile.
When we modify the variable with volatile, public volatile boolean sign = false;, thread 01 operates on the variable, forcing the value of the variable change to be refreshed to the main memory. When thread 02 gets the value, it expires the sign value in its own memory and then reads it from the main memory. So after adding keywords, the program outputs the results as expected.
4. Decompiler detoxification visibility
The best way to have in-depth technical knowledge like this is to have a deep understanding of the principle and see what it does to ensure memory visibility.
4.1 View JVM directives
"instruction": javap-v-p VT
Public volatile boolean sign
Descriptor: Z
Flags: ACC_PUBLIC, ACC_VOLATILE
Org.itstack.interview.test.VT ()
Descriptor: () V
Flags:
Code:
Stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial # 1 / / Method java/lang/Object. "() V
4: aload_0
5: iconst_0
6: putfield # 2 / / Field sign:Z
9: return
LineNumberTable:
Line 35: 0
Line 37: 4
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this Lorg/itstack/interview/test/VT
Public void run ()
Descriptor: () V
Flags: ACC_PUBLIC
Code:
Stack=2, locals=1, args_size=1
0: aload_0
1: getfield # 2 / / Field sign:Z
4: ifne 10
7: goto 0
10: getstatic # 3 / / Field java/lang/System.out:Ljava/io/PrintStream
13: ldc # 4 / / String, you are bad
15: invokevirtual # 5 / / Method java/io/PrintStream.println: (Ljava/lang/String;) V
18: return
LineNumberTable:
Line 40: 0
Line 42: 10
Line 43: 18
LocalVariableTable:
Start Length Slot Name Signature
0 19 0 this Lorg/itstack/interview/test/VT
StackMapTable: number_of_entries = 2
Frame_type = 0 / * same * /
Frame_type = 9 / * same * /
}
You can only find too much in the JVM script, ACC_VOLATILE, and nothing else. So, you can't see how the visibility is achieved.
4.2 View assembly instructions
To view the assembly through the Class file, you need to download the hsdis-amd64.dll file and copy it to the JAVA_HOME\ jre\ bin\ server directory. The download resources are as follows:
Http://vorboss.dl.sourceforge.net/project/fcml/fcml-1.1.1/hsdis-1.1.1-win32-amd64.ziphttp://vorboss.dl.sourceforge.net/project/fcml/fcml-1.1.1/hsdis-1.1.1-win32-i386.zip
The other is to execute orders, including:
Basic instruction: java-Xcomp-XX:+UnlockDiagnosticVMOptions-XX:+PrintAssembly specifies print:-XX:CompileCommand=dontinline, class name. The method name specifies the print:-XX:CompileCommand=compileonly, class name. Output location of method name: > xxx
Final use: java-Xcomp-XX:+UnlockDiagnosticVMOptions-XX:+PrintAssembly-XX:CompileCommand=dontinline,ApiTest.main-XX:CompileCommand=compileonly,ApiTest.mian
Instructions can be used in Terminal in IDEA or in the DOS black window
In addition, for easier use, we can configure the instruction into the VM options of idea, as shown in the following figure:
Idea VM options configuration compilation instruction
After the configuration is completed, the non-unexpected running results are as follows:
Loaded disassembler from C:\ Program Files\ Java\ jdk1.8.0_161\ jre\ bin\ server\ hsdis-amd64.dll
Decoding compiled method 0x0000000003744990:
Code:
Argument 0 is unknown.RIP: 0x3744ae0 Code size: 0x00000110
[Disassembling for mach='amd64']
[Entry Point]
[Constants]
# {method} {0x000000001c853d18} 'getSnapshotTransformerList'' () [Lsun/instrument/TransformerManager$TransformerInfo;' in 'sun/instrument/TransformerManager'
# [sp+0x40] (sp of caller)
0x0000000003744ae0: mov r10d,dword ptr [rdx+8h]
0x0000000003744ae4: shl r10,3h
0x0000000003744ae8: cmp r10,rax
0x0000000003744aeb: jne 3685f60h; {runtime_call}
0x0000000003744af1: nop word ptr [rax+rax+0h]
0x0000000003744afc: nop
[Verified Entry Point]
0x0000000003744b00: mov dword ptr [rsp+0ffffffffffffa000h], eax
0x0000000003744b07: push rbp
0x0000000003744b08: sub rsp,30h; * aload_0
;-sun.instrument.TransformerManager::getSnapshotTransformerList@0 (line 166)
0x0000000003744b0c: mov eax,dword ptr [rdx+10h]
0x0000000003744b0f: shl rax,3h; * getfield mTransformerList
;-sun.instrument.TransformerManager::getSnapshotTransformerList@1 (line 166)
0x0000000003744b13: add rsp,30h
...
"the result of the run is the assembly instruction." if there are more, they won't all be put here. We only observe. Key parts:
0x0000000003324cda: mov 0x74 (% R8),% edx; * getstatic state
;-VT::run@28 (line 27)
0x0000000003324cde: inc% edx
0x0000000003324ce0: mov% edx,0x74 (% R8)
0x0000000003324ce4: lock addl $0x0, (% rsp); * putstatic state
;-VT::run@33 (line 27)
In the compiled assembly instructions, there is a volatile keyword and no volatile keyword, the main difference is that there is a lock addl $0x0, (% rsp), that is, the prefix instruction of lock.
The "lock instruction" acts as a memory barrier and guarantees the following three points:
Write the cache of this processor to memory. When reordering, you cannot reorder subsequent instructions to the position in front of the memory barrier. If it is a write action, the corresponding memory in other processors will be invalid.
So, the 1 and 3 here are used to ensure the modified variables and memory visibility.
5. Can you see it without volatile?
Where there is doubt, there must be verification.
Let's now modify the example to add a piece of execution code to the body of the while (! sign) loop, as follows
Class VT implements Runnable {
Public boolean sign = false
Public void run () {
While (! sign) {
System.out.println ("Hello")
}
System.out.println ("you bad")
}
}
After modification, the volatile keyword is removed and a piece of code is added to the while loop. The result of the current operation is:
...
Hello
Hello
Hello
Vt.sign = true notifies while (! sign) to end!
You're bad.
Process finished with exit code 0 so far, I believe you have a deeper understanding of "how volatile is visible in memory". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.