当前位置:网站首页>30 minutes to thoroughly understand the synchronized lock upgrade process
30 minutes to thoroughly understand the synchronized lock upgrade process
2022-07-26 10:04:00 【Java confidant_】
Click on the official account , Practical technical articles Know in time
stay Java In the field of concurrent programming , We will use the lock during the meeting , For example, in the multi-threaded environment, in order to prevent some thread safety problems , There may be some unexpected problems , So I've sorted out a series about JDK The problem of middle lock , Help you understand them more deeply .
synchronized It's really a heavyweight lock ?
I believe most people have encountered this problem during the interview , The answer is No . This depends on JDK To judge . If JDK The version of is in 1.5 Before using synchronized
The principle of lock is as follows :
Add one before and after the resources that need to be locked “
monitorenter
” and “monitorexit
” Instructions .When a thread needs to enter this code critical area , Get involved first “ Grab the lock ”( The essence is to get monitor Authority )
If lock grabbing fails , Will be blocked , At this point, control can only be handed over to the operating system , It will start from
user mode
Switch tokernel mode
, The operating system is responsible for the scheduling between threads and the state change of threads , You need to switch between these two modes frequently ( Context conversion ).
It can be seen that , Under the condition of the old mode, the cost of obtaining locks is relatively large , So later JDK The author of JDK Designed in Lock Interface , use CAS To implement the lock , To improve performance .
But when the competition is very fierce , use CAS The way may not get the lock all the time , No matter how much CAS It's also a waste CPU, The performance loss in this state will be higher than synchronized
higher . So in this case , It's better to upgrade and lock directly , Let the operating system intervene .
Because of this , Therefore, there will be the saying of lock upgrade later .
synchronized Lock upgrade
Biased locking
stay synchronized
In the process of upgrading , The first step will be upgraded to bias lock . The so-called deflection lock , Its essence is to let the lock remember the requested thread .
In most scenarios , In fact, there are more single thread access locks ,JDK The author of is reconstructing synchronized
When , Designed a for the object header bit position , Specifically used to record lock information , Specifically, we can understand it through the following actual case :
public static void main(String[] args) throws InterruptedException {
Object o = new Object();
System.out.println(" The synchronization block has not been entered ");
System.out.println("markword:" + ClassLayout.parseInstance(o).toPrintable());
// Default JVM There will be a warm-up phase during startup , Therefore, the deflection lock will not be opened by default
Thread.sleep(5000);
Object b = new Object();
System.out.println(" The synchronization block has not been entered ");
System.out.println("markword:" + ClassLayout.parseInstance(b).toPrintable());
synchronized (o){
System.out.println(" Entering the synchronization block ");
System.out.println("markword:" + ClassLayout.parseInstance(o).toPrintable());
}
}
Pay attention to introducing some third-party dependencies , Help us view the information of the object header :
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
// This version number is different , The format of the viewed content is also different
<version>0.16</version>
</dependency>
The console output is as follows :
The synchronization block has not been entered
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
markword:java.lang.Object object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0xf80001e5
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
The synchronization block has not been entered
markword:java.lang.Object object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000005 (biasable; age: 0)
8 4 (object header: class) 0xf80001e5
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
Entering the synchronization block
markword:java.lang.Object object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x00007000050ee988 (thin lock: 0x00007000050ee988)
8 4 (object header: class) 0xf80001e5
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
In this case , If you carefully observe the contents of the console , You can find , When JVM When it started , The lock flag bit of the object head is unlocked . But after a whole child ( Probably 4 Seconds later ), It will become a biasable The state of . If you need to adjust the delay time , You can use the parameter -XX:BiasedLockingStartupDelay=0
To control .
Here I'll explain biasable
The meaning of :
biasable yes JVM Help us set the status , In this state , Once a thread accesses the lock , It's going to be direct CAS Modify the thread in the object header id. If it works , Then directly upgrade to bias lock . Otherwise, it will enter the next state of the lock -- Lightweight lock .
ps:JVM Because during the warm-up phase , There are many steps to use synchronized
, So before just starting 4 In the second , Will not directly synchronized
The mark of the lock is upgraded to biasable
state . This is to reduce some unnecessary performance losses .
Lightweight lock
When a lock is accessed by a thread , It will become a biased lock state , When the new thread accesses the lock again , Will there be any change in the lock ?
Here I have sorted out a flow chart of lock changes , As shown below :
To verify this process , We can practice through the following case :
public static void main(String[] args) throws InterruptedException {
// sleep 5s
Thread.sleep(5000);
Object o = new Object();
System.out.println(" Synchronization block not entered ,MarkWord by :");
System.out.println(ClassLayout.parseInstance(o).toPrintable());
synchronized (o){
System.out.println((" Go into sync block ,MarkWord by :"));
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
Thread t2 = new Thread(() -> {
synchronized (o) {
System.out.println(" The new thread acquires the lock ,MarkWord by :");
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
});
t2.start();
t2.join();
System.out.println(" The main thread looks at the lock object again ,MarkWord by :");
System.out.println(ClassLayout.parseInstance(o).toPrintable());
synchronized (o){
System.out.println((" The main thread enters the synchronization block again ,MarkWord by :"));
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
synchronized (b) {
System.out.println((" The main thread enters the synchronization block again , And call hashcode Method ,MarkWord by :"));
b.hashCode();
System.out.println(ClassLayout.parseInstance(b).toPrintable());
}
}
Then let's observe the results of the implementation :
/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/bin/java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:63267,suspend=y,server=n -javaagent:/Users/linhao/Library/Caches/IntelliJIdea2019.3/captureAgent/debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/lib/tools.jar:/Users/linhao/IdeaProjects/my-github/concurrence-programming-lession/target/classes:/Users/linhao/.m2/repository/org/junit/jupiter/junit-jupiter/5.9.0-RC1/junit-jupiter-5.9.0-RC1.jar:/Users/linhao/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.5.2/junit-jupiter-api-5.5.2.jar:/Users/linhao/.m2/repository/org/apiguardian/apiguardian-api/1.1.0/apiguardian-api-1.1.0.jar:/Users/linhao/.m2/repository/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar:/Users/linhao/.m2/repository/org/junit/platform/junit-platform-commons/1.5.2/junit-platform-commons-1.5.2.jar:/Users/linhao/.m2/repository/org/junit/jupiter/junit-jupiter-params/5.5.2/junit-jupiter-params-5.5.2.jar:/Users/linhao/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.5.2/junit-jupiter-engine-5.5.2.jar:/Users/linhao/.m2/repository/org/junit/platform/junit-platform-engine/1.5.2/junit-platform-engine-1.5.2.jar:/Users/linhao/.m2/repository/org/openjdk/jol/jol-core/0.16/jol-core-0.16.jar:/Users/linhao/.m2/repository/org/apache/dubbo/dubbo/2.7.8/dubbo-2.7.8.jar:/Users/linhao/.m2/repository/org/springframework/spring-context/5.2.5.RELEASE/spring-context-5.2.5.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/spring-aop/5.2.5.RELEASE/spring-aop-5.2.5.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/spring-beans/5.2.5.RELEASE/spring-beans-5.2.5.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/spring-expression/5.2.5.RELEASE/spring-expression-5.2.5.RELEASE.jar:/Users/linhao/.m2/repository/com/alibaba/spring/spring-context-support/1.0.8/spring-context-support-1.0.8.jar:/Users/linhao/.m2/repository/org/javassist/javassist/3.20.0-GA/javassist-3.20.0-GA.jar:/Users/linhao/.m2/repository/io/netty/netty-all/4.1.48.Final/netty-all-4.1.48.Final.jar:/Users/linhao/.m2/repository/com/google/code/gson/gson/2.8.6/gson-2.8.6.jar:/Users/linhao/.m2/repository/org/yaml/snakeyaml/1.25/snakeyaml-1.25.jar:/Users/linhao/.m2/repository/com/alibaba/fastjson/1.2.70/fastjson-1.2.70.jar:/Users/linhao/.m2/repository/org/apache/zookeeper/zookeeper/3.5.3-beta/zookeeper-3.5.3-beta.jar:/Users/linhao/.m2/repository/commons-cli/commons-cli/1.2/commons-cli-1.2.jar:/Users/linhao/.m2/repository/io/netty/netty/3.10.5.Final/netty-3.10.5.Final.jar:/Users/linhao/.m2/repository/org/apache/dubbo/dubbo-spring-boot-starter/2.7.8/dubbo-spring-boot-starter-2.7.8.jar:/Users/linhao/.m2/repository/org/apache/dubbo/dubbo-spring-boot-autoconfigure/2.7.8/dubbo-spring-boot-autoconfigure-2.7.8.jar:/Users/linhao/.m2/repository/org/apache/dubbo/dubbo-spring-boot-autoconfigure-compatible/2.7.8/dubbo-spring-boot-autoconfigure-compatible-2.7.8.jar:/Users/linhao/.m2/repository/org/springframework/boot/spring-boot-starter/2.2.6.RELEASE/spring-boot-starter-2.2.6.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/boot/spring-boot/2.2.6.RELEASE/spring-boot-2.2.6.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.2.6.RELEASE/spring-boot-autoconfigure-2.2.6.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.2.6.RELEASE/spring-boot-starter-logging-2.2.6.RELEASE.jar:/Users/linhao/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/Users/linhao/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/Users/linhao/.m2/repository/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar:/Users/linhao/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.12.1/log4j-to-slf4j-2.12.1.jar:/Users/linhao/.m2/repository/org/apache/logging/log4j/log4j-api/2.12.1/log4j-api-2.12.1.jar:/Users/linhao/.m2/repository/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30.jar:/Users/linhao/.m2/repository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/Users/linhao/.m2/repository/org/springframework/spring-core/5.2.5.RELEASE/spring-core-5.2.5.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/spring-jcl/5.2.5.RELEASE/spring-jcl-5.2.5.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.2.6.RELEASE/spring-boot-starter-web-2.2.6.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.2.6.RELEASE/spring-boot-starter-json-2.2.6.RELEASE.jar:/Users/linhao/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.10.3/jackson-databind-2.10.3.jar:/Users/linhao/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.10.3/jackson-annotations-2.10.3.jar:/Users/linhao/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.10.3/jackson-core-2.10.3.jar:/Users/linhao/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.10.3/jackson-datatype-jdk8-2.10.3.jar:/Users/linhao/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.10.3/jackson-datatype-jsr310-2.10.3.jar:/Users/linhao/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.10.3/jackson-module-parameter-names-2.10.3.jar:/Users/linhao/.m2/repository/org/springframework/boot/spring-boot-starter-validation/2.2.6.RELEASE/spring-boot-starter-validation-2.2.6.RELEASE.jar:/Users/linhao/.m2/repository/jakarta/validation/jakarta.validation-api/2.0.2/jakarta.validation-api-2.0.2.jar:/Users/linhao/.m2/repository/org/hibernate/validator/hibernate-validator/6.0.18.Final/hibernate-validator-6.0.18.Final.jar:/Users/linhao/.m2/repository/org/jboss/logging/jboss-logging/3.4.1.Final/jboss-logging-3.4.1.Final.jar:/Users/linhao/.m2/repository/com/fasterxml/classmate/1.5.1/classmate-1.5.1.jar:/Users/linhao/.m2/repository/org/springframework/spring-web/5.2.5.RELEASE/spring-web-5.2.5.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/spring-webmvc/5.2.5.RELEASE/spring-webmvc-5.2.5.RELEASE.jar:/Users/linhao/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.2.6.RELEASE/spring-boot-starter-tomcat-2.2.6.RELEASE.jar:/Users/linhao/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.33/tomcat-embed-core-9.0.33.jar:/Users/linhao/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/9.0.33/tomcat-embed-el-9.0.33.jar:/Users/linhao/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.33/tomcat-embed-websocket-9.0.33.jar:/Users/linhao/.m2/repository/org/apache/curator/curator-framework/2.12.0/curator-framework-2.12.0.jar:/Users/linhao/.m2/repository/org/apache/curator/curator-client/2.12.0/curator-client-2.12.0.jar:/Users/linhao/.m2/repository/com/google/guava/guava/16.0.1/guava-16.0.1.jar:/Users/linhao/.m2/repository/org/apache/curator/curator-recipes/2.12.0/curator-recipes-2.12.0.jar:/Users/linhao/.m2/repository/com/alibaba/transmittable-thread-local/2.12.2/transmittable-thread-local-2.12.2.jar:/Users/linhao/.m2/repository/org/apache/rocketmq/rocketmq-client/4.8.0/rocketmq-client-4.8.0.jar:/Users/linhao/.m2/repository/org/apache/rocketmq/rocketmq-common/4.8.0/rocketmq-common-4.8.0.jar:/Users/linhao/.m2/repository/org/apache/rocketmq/rocketmq-remoting/4.8.0/rocketmq-remoting-4.8.0.jar:/Users/linhao/.m2/repository/org/apache/rocketmq/rocketmq-logging/4.8.0/rocketmq-logging-4.8.0.jar:/Users/linhao/.m2/repository/io/netty/netty-tcnative-boringssl-static/2.0.30.Final/netty-tcnative-boringssl-static-2.0.30.Final.jar:/Users/linhao/.m2/repository/commons-validator/commons-validator/1.6/commons-validator-1.6.jar:/Users/linhao/.m2/repository/commons-beanutils/commons-beanutils/1.9.2/commons-beanutils-1.9.2.jar:/Users/linhao/.m2/repository/commons-digester/commons-digester/1.8.1/commons-digester-1.8.1.jar:/Users/linhao/.m2/repository/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:/Users/linhao/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar:/Users/linhao/.m2/repository/org/apache/commons/commons-lang3/3.9/commons-lang3-3.9.jar:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar" Concurrent programming 03. View memory layout information .MarkWordDemo_4
Connected to the target VM, address: '127.0.0.1:63267', transport: 'socket'
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
Synchronization block not entered ,MarkWord by :java.lang.Object object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0xf80001e5
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
Synchronization block not entered ,MarkWord by :java.lang.Object object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000005 (biasable; age: 0)
8 4 (object header: class) 0xf80001e5
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
Go into sync block ,MarkWord by :java.lang.Object object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x00007fe8a5009805 (biased: 0x0000001ffa294026; epoch: 0; age: 0)
8 4 (object header: class) 0xf80001e5
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
The new thread acquires the lock ,MarkWord by :
java.lang.Object object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x000070000ba03908 (thin lock: 0x000070000ba03908)
8 4 (object header: class) 0xf80001e5
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
The main thread looks at the lock object again ,MarkWord by :
java.lang.Object object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0xf80001e5
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
The main thread enters the synchronization block again ,MarkWord by :
java.lang.Object object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000700009f87980 (thin lock: 0x0000700009f87980)
8 4 (object header: class) 0xf80001e5
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
The main thread enters the synchronization block again , And call hashcode Method ,MarkWord by :
java.lang.Object object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x00007fe8a51391ea (fat lock: 0x00007fe8a51391ea)
8 4 (object header: class) 0xf80001e5
12 4 (object alignment gap)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
Disconnected from the target VM, address: '127.0.0.1:63267', transport: 'socket'
Process finished with exit code 0
Through the print content in the console, we can find , The state of the lock has gone through the following steps :
biasable state
In this state , Lock is a state to be biased , At this time, if there is a thread request . But if it is just started JVM The state of the word , The head of the object will be non-biasable state , Only wait jvm Warm up for a period of time ( It's about 4 second ), Will stay and turn into biasable state .
biased state
When the first request obtains the lock , The lock state will become biased to the lock state , That is to say biased. If you are in the biased lock state , There are also new threads involved in lock grabbing , Then lock escalation will occur , Enter the lightweight lock state stage .
thin lock state
You can see , When a lock has experienced a biased lock state , Later, if another thread accesses it , It will be upgraded to the state of lightweight lock , That is to say thin lock state .
fat lock state
When we call hashcode Method time , Will find , The head of the lock object will have an extra one called fat lock The state of , That means , At this time, the lock has been upgraded to a heavyweight lock .
Heavyweight lock
When a lock is already in the state of lightweight lock , If there are more threads trying to acquire the lock , Then the lock will be accessed by multiple threads in a spinning way , When the number of visits reaches a certain limit ,synchronized
It will be automatically upgraded to the state of heavyweight lock .
When upgrading to a heavyweight lock , Lock object's mark word
The pointer in no longer points to lock record
, It points to the lock object in the heap monitor
object . When multiple threads access synchronous code at the same time , These threads will first try to get the corresponding value of the current lock object monitor
The ownership of the :
To be successful , Determine whether the current thread is reentrant , If it's reentry, then
recursions+1
Acquisition failure , The current thread will be blocked , Waiting for other threads to be awakened after unlocking , Compete for lock objects again
In the case of heavyweight locks , The process of adding and unlocking involves the operation of the operating system Mutex Lock
Do mutually exclusive operations , The scheduling between threads and the state change process of threads need to switch between user state and core state , It's going to consume a lot of cpu resources , Resulting in reduced performance .
What are several ways to upgrade a lock to a heavyweight state ?
call wait Method
Call the... Of the object in the synchronized code block hashcode Method
Finally, I drew a flow chart of lock upgrade to share with you :

Summary
Actually JVM Have been to synchronized
optimized . It can be used directly , As for the strength of the lock ,JVM The bottom layer is ready. We can use it directly . But as an engineer , Understanding these underlying principles can still increase our internal skills .
recommend
Technical involution group , Learn together !!
PS: Because the official account platform changed the push rules. , If you don't want to miss the content , Remember to click after reading “ Looking at ”, Add one “ Star standard ”, In this way, each new article push will appear in your subscription list for the first time . spot “ Looking at ” Support us !
边栏推荐
- Encapsulation of tabbarcontroller
- [information system project manager] summary of essence of high-level series for the first time
- Spolicy request case
- Vs2019 configuring opencv
- 新公链Aptos何以拉满市场期待值?
- Strange Towers of Hanoi|汉诺塔4柱问题
- WARNING: [pool www] server reached pm. max_ children setting (5), consider raising it
- Wechat applet learning notes 2
- Yarn 'TSC' is not an internal or external command, nor is it a runnable program or batch file. The problem that the command cannot be found after installing the global package
- Formwork (III)
猜你喜欢
The problem of accessing certsrv after configuring ADCs
Mysql5.7.25 master-slave replication (one-way)
服务发现原理分析与源码解读
Applet record
Error in render: "typeerror: cannot read properties of undefined (reading 'length')" --- error when calling interface
Apple dominates, Samsung revives, and domestic mobile phones fail in the high-end market
MQTT X CLI 正式发布:强大易用的 MQTT 5.0 命令行工具
Vs Code configures go locale and successfully installs go related plug-ins in vscode problem: Tools failed to install
Use of tabbarcontroller
R language ggplot2 visualization: align the legend title to the middle of the legend box in ggplot2 (default left alignment, align legend title to middle of legend)
随机推荐
2021年山东省中职组“网络空间安全”B模块windows渗透(解析)
regular expression
Use of tabbarcontroller
解释一下自动装箱和自动拆箱?
Map key not configured and uniapp routing configuration and jump are reported by the uniapp < map >< /map > component
云原生(三十六) | Kubernetes篇之Harbor入门和安装
服务发现原理分析与源码解读
数通基础-STP原理
Azkaban【基础知识 01】核心概念+特点+Web界面+架构+Job类型(一篇即可入门Azkaban工作流调度系统)
Due to fierce competition in the new market, China Mobile was forced to launch a restrictive ultra-low price 5g package
QT handy notes (III) use qtcharts to draw a line chart in VS
Leetcode 504. Hex number
Explain automatic packing and unpacking?
Cloud native (36) | introduction and installation of harbor in kubernetes
在Blazor 中自定义权限验证
copyTo
Getting started with SQL - combined tables
Interview shock 68: why does TCP need three handshakes?
Flutter event distribution
Rowselection emptying in a-table