当前位置:网站首页>Synchonized introduction
Synchonized introduction
2022-06-25 05:37:00 【Which floor do you rate moto】
Catalog
synchronized Underlying principle
Synchronized Reentrant implementation mechanism of
Synchronized Of 8 Lock phenomenon
Prerequisite knowledge
In multithreaded programming , It is possible for multiple threads to access the same shared variable at the same time , Variable resources , This resource is called critical resource ; This resource object may be : object , Variable , Documents, etc. .
- share : Resources can be accessed simultaneously by multiple threads
- variable : A resource can be modified during its life cycle
The questions that come out :
- Because the process of thread execution is uncontrollable , So we need to adopt the synchronization mechanism to coordinate the access to the variable state of the object !
How to solve the thread concurrency safety problem
- actually , All concurrency modes are used to solve thread safety problems , The solutions are serialization access critical resources . At the same time , Only one thread can access critical resources , Also known as synchronous mutually exclusive access .
- Java in , There are two ways to achieve synchronous exclusive access :synchronized and Lock
Synchronized Introduce
- Built in lock , Implicit lock ( Locking and unlocking are invisible )
- Synchronized Methods are not inherited , You need to specify again in the subclass
Process performed : You can click the link to zoom in and view the clear picture

Detailed flow chart :

Synchronized Use scenarios
We use it normally Synchronized It is usually used in the following scenarios :
- Decorated instance method : For the current instance object this Lock
public class Synchronized {
public synchronized void husband(){
}
}- Modified static method : For the current class Class Object locking
public class Synchronized {
public static synchronized void husband(){
}
}- Decorated code block , Specify a locked object , Lock the object
public class Synchronized {
public void husband(){
Object object = new Object()
synchronized(object ){
}
}
}synchronized Underlying principle
- synchronized Built in lock is a kind of Object lock ( It's the object that locks, not the reference ), Action granularity is the object , It can be used to realize synchronous exclusive access to critical resources
- synchronized Is based on JVM Built in lock implementation , Through internal objects Monitor( Monitor lock ) Realization , Based on entry and exit Monitor Object implementation methods are synchronized with code blocks , The implementation of monitor lock depends on the underlying operating system Mutex lock( The mutex ) Realization , It is a heavyweight lock with low performance . Of course ,JVM Built in lock in 1.6 Then there was a major optimization , Such as lock coarsening , Lock elimination , Lightweight lock , Biased locking , Adaptive spin and other techniques to reduce the overhead of lock operation , The concurrency of built-in locks can be basically Lock flat
- Synchronized Keywords are compiled into bytecode and translated into monitorenter and monitorexit The two instructions are at the start and end of the logic code of the synchronous code block

- Each synchronization object has its own Monitor( Monitor lock ), The locking process is as follows

- Synchronized After decompiling the modified code block, an extra one will appear monitorexit: In case of exception, it is required to release the lock and exit completely

- When decorating a method, there will be one more modifier for the decompiled method SYS_SYNCHRONIZED( Indicates that the current method needs to be locked ),JVM In executing this method , If you encounter this sign , Before entering this method , Will lock the current method

Synchronized Reentrant implementation mechanism of
When executed monitorenter when , If the counter of the target lock object is zero , It means that it is not held by other threads ,java The virtual opportunity sets the holding thread of the object as the current thread , And add it to the counter 1, When the counter of the target object is not zero , If the thread holding the lock object is the current thread , that java Virtual machine can add its counter 1, Otherwise you need to wait , Until the holding thread releases the lock , When executed monitorexit when ,java The virtual machine needs to decrement the counter of the lock object 1, The counter for 0 Indicates that the lock has been released . Threads are no longer monitor The owner of the ,, Others are monitor Blocked threads can try to get this monitor The ownership of the
Through the above two paragraphs ,Synchronized The bottom semantic layer is through a monitor To complete ,wait and notify And so on monitor object ( This is why only synchronized blocks or methods can be called wait and notify, Otherwise it will throw java.lang.IIIegalMonitorStateException)
Method synchronization : Compared to the normal method , There are more constant pools ACC_SYNCHRONIZED identifier ,JVM The synchronization of methods is implemented according to identifiers :
Method is called , The call instruction will check the method's ACC_SYNCHRONIZED Whether the access flag is set , If set , Execution thread will get first monitor, The method body can only be executed after it is successfully obtained , Method can only be released after its execution monitor. During method execution , No other thread can get the same monitor object
When two instructions are executed JVM By calling the mutually exclusive source language of the operating system mutex To achieve , Blocked threads will be suspended , Waiting for rescheduling , It can lead to " User mode and kernel mode " The two states switch back and forth , It has a great impact on the performance
Monitor Monitor lock
Every object has a Monitor Associated with it , When and one Monitor After being held , He will be locked .Synchronized stay JVM The implementation in is based on entry and exit Monitor Object to synchronize methods and code blocks , Although the implementation details are different , But you can pass MonitorEnter and MonitorExit Instructions to implement .
- MonitorEnter: Each object is a monitor lock (Monitor), When Monitor When occupied, it will be locked , Threads execute MonitorEnter Attempt to get Monitor The ownership of the , The process is as follows :
- a. If monitor The number of entries is 0, Then the thread enters monitor, Then set the number of entries to 1, Improvement process Monitor Owner
- b. If the thread already owns the Monitor, Just re-enter , entering Monitor The number of entries plus 1
- c. If other threads are already occupied monitor, Then the thread enters the blocking state , until monitor The number of entries is 0, Try again to get monitor The ownership of the
- Monitorexit: perform Monitor The thread of must be Monitorenter Corresponding owner . Instruction execution ,monitor The number of entries minus 1, If less 1 The last in number is 0, The thread exits monitor, It's not this anymore Monitor Owner , Others are Monitor Blocked threads can try to get this monitor The ownership of the .Monitorexit It appears twice , The first step is to release the lock when the synchronization exits normally , The second time is to release the lock in case of asynchronous exit
Through the above description , We should be able to see clearly synchronized Implementation principle of ,synchronized The bottom semantic layer is through a monitor To complete , Actually wait/notify And so on monitor object , That's why it can only be called in synchronized blocks or methods wait/notify Other methods , Otherwise it will throw lllegalMonitorStateException The cause of the abnormality .
From the compilation results , Method synchronization did not go through the instructions monitorenter and monitorexit To complete ( Theoretically, it can also be realized through these two instructions ), But compared to the normal way , Its constant pool is correct ACC_SYNCHRONZIED identifier ,JVM The synchronization of methods is realized according to the identifier : Method call , The call instruction will check ACC_SYNCHRONZIED Whether the access flag is set , If set , The execution thread will get monitor. The method body can only be executed after it is successfully obtained , Methods are released after they are released monitor, During method execution , No other thread can get the same monitor object
There is essentially no difference between the two synchronization methods , But method synchronization is an implicit way to achieve , No bytecode required . The execution of the two instructions is JVM By calling the operating system's mutex primitive mutex To achieve , Blocked threads will be suspended , Waiting for rescheduling , It can lead to " User mode and kernel mode " Switching back and forth between two states , It has a great impact on the performance .
What is? monitor
You can put Monitor Understood as a A synchronization tool , It can also be described as A synchronization mechanism , It usually Described as an object , Like everything , be-all Java The object is natural Monitor, every last Java Objects can become Monitor The potential to , Because in Java In the design of , every last Java The object hits itself new I came out with an invisible lock , He handed it in as an internal lock or Monitor lock , That is to say Synchronzied Object lock ,MarkWord Lock identification is 10, Where the pointer points to Monitor The starting address of the object . stay Java In the virtual machine (HotSpot in )Monitor By ObjectMonitor Realized , The main data results are as follows ( be located HotSpot Virtual machine source code ObjectMonitor.hpp file ,C++ Realized ):

objectMonitor There are two queues in ,_WaitSet and _EntrySet For preservation ObjectWaiter The object list ( Every thread waiting for a lock is encapsulated as ObjectWaiter object ), _owner To hold ObjectMnitor Object's thread , When multiple threads access a piece of synchronous code at the same time :
- First of all _Entrylist aggregate , When the thread gets the monitor after , Get into _Owner Area and put monitor Medium owner Variable set to current thread , meanwhile monitor The counter in count Add 1;
- If the thread calls wait() Method , Will release what is currently held monitor,owner The variable returns to null.count Self reduction 1, At the same time, the thread enters WaitSet Waiting to be awakened in the assembly ;
- If the current thread is finished , Will release monitor( lock ) And reset count Value , So that other threads can enter monitor( lock )
meanwhile ,Monitor The object exists in every Java Object head of object Mark Word( The point of the stored pointer ),Synchronized Lock is obtained by this way , That's why Java Any object in can be used as the reason for the lock , meanwhile notify/notifyAll/wait And other methods will be used to Monitor Lock object , So it has to be used in synchronous code blocks . The monitor Monitor There are two ways to synchronize : Mutual exclusion and collaboration . In multithreading environment, if threads need to share data , We need to solve the problem of mutually exclusive access to data , The monitor can ensure that only one thread can access the data on the monitor at the same time .
We know synchronzied To attach a lock to an object , How does an object record the state of a lock ?? The answer is The lock state is recorded in the object header of each object (Mark Word) in
Object layout
About object layout in JVM Will also be introduced to
HotSpot In the virtual machine , The layout of objects stored in memory can be divided into three areas : Object head (Header), The instance data (Instance Data), Alignment filling (Padding0)
- Object head : There are two parts of information , The first part is "Mark Word", Used to store runtime data of the object itself , such as Hash code , The age of the object , Object lock , Lock status information , Biased locking ( Threads )ID, Time bias, etc , It is the key to achieving lightweight and biased locking . The length of this part of data is 32 Bit and 64 The virtual machines of bit are respectively 32 and 64 individual Bits, Officially called "Mark Word". Objects need to store a lot of runtime data , In fact, it has surpassed 32,64 position Bitmap Limits that can be recorded by the structure , But the object header information is an extra storage cost independent of the data defined by the object itself , Consider the spatial efficiency of the virtual machine ,Mark Word It is designed as a flexible data structure to store as much information as possible in a very small space , He will reuse his storage space according to the state of the object , For example, in 32 Bit HotSpot A virtual machine in which objects are not locked ,Mark Word Of 32 individual Bits In the space 25Bits For storing objects (HashCode),4Bits Used to store object generational ages ,2Bits Used to store lock flag bits ,1Bit Fixed for 0, In other states ( Lightweight locking , Heavyweight lock ,GC Mark , Can be biased ) The storage contents of the following objects are shown in the following table .
- Java The object header generally takes two machine codes ( stay 32 In virtual machine ,1 A machine code is equal to 4 Bytes , That is to say 32bit, stay 64 In virtual machine ,1 A machine code means 8 One byte is 64bit),
- But if the object is an array type , You need to 3 A machine code , because JVM Virtual machines can be accessed through Java Object metadata information determination Java Size of object , Singular cannot confirm the length of the array from the metadata of the data , So use a block to record the data length
- The instance data : Store the attribute data information of the class ; Including the attribute information of the parent class
- Alignment filling : because The virtual machine requires that the size of the object must be 8 Integer multiples of bytes , Filling data is not necessary , Just for byte alignment
chart :

Object header information is an additional storage cost independent of the data defined by the object itself , Consider the spatial efficiency of the virtual machine ,Mark Word It is designed as a flexible data structure to store as much information as possible in a very small space , He will reuse his storage space according to the state of the object, that is to say : Mark Word(4 byte ) The internal information will be updated as the lock changes :

- Lightweight lock :2 Bit is the lock flag bit , rest 30 Bits are pointers to lock records in the stack
- Heavyweight lock :2 Bit is the lock flag bit , rest 30 Bits all point to mutexes ( heavyweight ) The pointer to
- It can be seen from the picture that : Object's hashCode In lightweight locks , Under the three states of heavyweight lock and bias lock hashcode Where is the record
- Biased locks do not store objects hashCode, If this is a deflection lock , Call the object's hashCode, In fact, the system delay calculation will be called hashCode One way , This will cause the biased lock to be upgraded to a lightweight lock .
- The lightweight lock will be the object's hashCode Record the... Of the online stack Replace lock Record in , At the same time, the original bias lock will be degraded ( Not really demoted ) Is unlocked ( Can save objects hashCode) And save the lock free state MarkWord Saved to the thread stack Replace lock Record in , Lightweight 30 The bit pointer will point to the stack and save to MarkWord. Simultaneous thread stack Replace lock Record Stored in the MarkWord The pointer inside will also point to the lightweight lock MarkWord.
- Heavyweight lock hashcode Recorded in the monitor in

public static void main(String[] args) {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object o = new Object();
System.out.println(ClassLayout.parseInstance(o).toPrintable());
synchronized (o){
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
// Output hashcode
System.out.println(o.hashCode());
System.out.println(ClassLayout.parseInstance(o).toPrintable());
synchronized (o){
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
}
// Print the results (1): Unlocked ( Anonymity bias , Biased state ): Have prepared to be partial to , Threads can come and get
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) e5 01 00 20 (11100101 00000001 00000000 00100000) (536871397)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
// Print the results (2): Biased locking
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 40 11 05 (00000101 01000000 00010001 00000101) (85016581)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) e5 01 00 20 (11100101 00000001 00000000 00100000) (536871397)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
// Printed hashcode: 517380410
// Print the results (3): Biased lock state call hashcode After the method , The lock status is unlocked ( The information is stored in the stack of lightweight locks )
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 3a 99 d6 (00000001 00111010 10011001 11010110) (-694601215)
4 4 (object header) 1e 00 00 00 (00011110 00000000 00000000 00000000) (30)
8 4 (object header) e5 01 00 20 (11100101 00000001 00000000 00100000) (536871397)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
// Print the results (4): It is shown as a lightweight lock
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) f0 f5 ca 04 (11110000 11110101 11001010 00000100) (80410096)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) e5 01 00 20 (11100101 00000001 00000000 00100000) (536871397)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total// Print a dependency on an object's memory area
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>
// Calling method
ClassLayout.parseInstance( Object name ).toPrintable();
public static void main(String[] args) {
Object o = new Object();
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
// Printed results
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) e5 01 00 20 (11100101 00000001 00000000 00100000) (536871397)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
//Mark Word Information about
// The operating system is divided into : Big end mode and small end mode , The small end mode should be changed to the large end mode
00000001 00000000 00000000 00000000 ==> 00000000 00000000 00000000 00000001
Lock flag position :001( No lock state )
hashcode For lazy load mode , At the beginning, there was no
Object o = new Object();
synchronized (o){
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
// Print information
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) b8 f6 11 05 (10111000 11110110 00010001 00000101) (85063352)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) e5 01 00 20 (11100101 00000001 00000000 00100000) (536871397)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
10111000 11110110 00010001 00000101 ==> 00000101 00010001 11110110 10111000
Lock flag position :00( Lightweight lock state ) ???? Why is it a lightweight state , According to the front lock expansion , Shouldn't it be a deflection lock
interpretative statement : JVM Will delay the activation of the bias lock :JVM I will rely on a lot of hashmap as well as class class , There are also a large number of synchronized code blocks , Multiple threads will also be started internally , There is internal competition , In order to avoid bias lock -> Lightweight lock -> The process of upgrading heavyweight locks , Delay using lightweight locks ( If you want to see accurate information , Need to delay 5 second )
public static void main(String[] args) {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object o = new Object();
System.out.println(ClassLayout.parseInstance(o).toPrintable());
synchronized (o){
System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
}
// Two printouts
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 00 00 00 (00000101 00000000 00000000 00000000) (5)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) e5 01 00 20 (11100101 00000001 00000000 00100000) (536871397)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 40 2a 05 (00000101 01000000 00101010 00000101) (86654981)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) e5 01 00 20 (11100101 00000001 00000000 00100000) (536871397)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
Delay 5s After opening the deflection lock
// Unlocked ( Anonymity bias , Biased state ): Have prepared to be partial to , Threads can come and get
00000101 00000000 00000000 00000000 ==> 00000000 00000000 00000000 00000101
// Finish locking ( Once a thread enters , Immediately bias to the current thread )
00000101 01000000 00101010 00000101 ==> 00000101 00101010 01000000 00000101
Synchronized Of 8 Lock phenomenon
When a thread tries to access a synchronized block of code , It must first obtain a lock , Release the lock when exiting or throwing an exception .
That is to say, if the non static synchronization method of an instance object acquires the lock , Other non static synchronous methods of the instance object must wait for the method that obtains the lock to release the lock , To get the lock ; However, the non static synchronization method of other instance objects uses different locks from the non static synchronization method of this instance object , therefore , You can acquire their own locks without waiting for the instance object to acquire the lock released by the non static synchronous method .
All static synchronization methods also use a lock - Class itself
These two locks are different objects , Therefore, there is no competition between static synchronization methods and non static synchronization methods .
But after a static synchronization method obtains the lock , Other static synchronization methods must wait for the method to release the lock , To get the lock
Be careful : Is it the same lock ( The non - static synchronous method lock is the caller who calls this method , Static synchronous methods lock the class itself , It mainly distinguishes these two points , There will be no misjudgment )
Specific code examples can be viewed synchronized Eight lock phenomenon , understand synchronized The use of _ Little bear -CSDN Blog
边栏推荐
猜你喜欢

ERDAS 9.2 installation tutorial
![[OSPF routing calculation (class I LSA router, class II LSA network, and class III LSA sum net)] -20211228-30](/img/c7/e38a7a5cd4c1e4105c3f3f246276c6.jpg)
[OSPF routing calculation (class I LSA router, class II LSA network, and class III LSA sum net)] -20211228-30

Code learning-cvpr2020 unsupervised domain adaptive semantic segmentation: intra advance

Enhanced paste quill editor

Professional things use professional people

Mirror image of binary tree

渗透测试-提权专题

I got to know data types and function variables for the first time. I learned data types and function variables together today and yesterday, so I saved them in the first issue to record.

C language -- Sanzi chess

Word quickly makes multiple single-sided table labels, number plates, etc
随机推荐
A brief talk on media inquiry
Various pits encountered in the configuration of yolov3 on win10
3.2.3 use tcpdump to observe TCP header information (supplement common knowledge of TCP protocol)
Pytorch- daily learning notes of some small functions involving training
DOM document object model (I)
Get the first letter of Chinese phonetic alphabet in Excel and capitalize it
JS function to realize simple calculator
Database query optimization method
Dynamic programming Backpack - 01 Backpack
2022.1.21 diary
Create dynamic array
Visual studio 2022 interface beautification tutorial
Array: force deduction dichotomy
Page electronic clock (use js to dynamically obtain time display)
Transformations of pytorch torch torch vision
C language - minesweeping
Classic usage of the sumproduct function
Go Basics
Tanhaoqiang C language practice
Creation and use of MySQL index
