In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
How to deeply analyze the implementation principle of synchronized, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain in detail for you, people with this need can come to learn, I hope you can gain something.
I remember that when we just started to learn Java, when we encountered multithreading, it was synchronized. Relative to us at that time, synchronized was so magical and powerful. At that time, we gave it a name "synchronization". It also became a good medicine for us to solve the multithreaded situation. However, as we learn, we know that synchronized is a heavyweight lock, and it will be so bulky compared to Lock that we think it is not so efficient and slowly abandon it.
Admittedly, with the various optimizations made to synchronized by Javs SE 1.6, synchronized will not seem so heavy. Following LZ, we will explore the implementation mechanism of synchronized, how Java optimizes it, the lock optimization mechanism, the lock storage structure and the upgrade process.
Realization principle
Synchronized can guarantee that when a method or code block is running, only one method can enter the critical area at a time, and it can also ensure the memory visibility of shared variables.
Every object in Java can be used as a lock, which is the basis for synchronized to achieve synchronization:
Ordinary synchronization method, where the lock is the current instance object
Static synchronization method, where the lock is the class object of the current class
Synchronous method block, and the lock is the object in parentheses
When a thread accesses a synchronous code block, it first needs to get a lock to execute the synchronous code, and when it exits or throws an exception, it must release the lock, so how does it implement this mechanism? Let's first look at a simple piece of code:
1234567891011public class SynchronizedTest {public synchronized void test1 () {} public void test2 () {synchronized (this) {}
Use javap tool to view the information of the generated class file to analyze the implementation of Synchronize
As you can see from the above, the synchronization code block is implemented using monitorenter and monitorexit instructions, and the synchronization method (which is not visible here needs to look at the underlying implementation of JVM) relies on the ACC_SYNCHRONIZED implementation on the method modifier.
Synchronous code block: the monitorenter instruction is inserted at the beginning of the synchronous code block, and the monitorexit instruction is inserted at the end of the synchronous code block. JVM needs to ensure that each monitorenter has a monitorexit corresponding to it. Any object has a monitor associated with it, and when and a monitor is held, it will be locked. When the thread executes the monitorenter instruction, it will attempt to acquire the monitor ownership corresponding to the object, that is, to attempt to acquire the lock of the object.
Synchronous method: the synchronized method is translated into ordinary method calls and return instructions such as invokevirtual and areturn instructions. There are no special instructions at the VM bytecode level to implement the method modified by synchronized, but the synchronized flag position 1 in the access_flags field of the method in the method table of the Class file. Indicates that the method is a synchronous method and uses the object calling the method or the Class to which the method belongs to represent the Klass as a lock object inside the JVM. (extracted from: http://www.cnblogs.com/javaminer/p/3889023.html)
Let's move on to the analysis, but before we go any further, we need to understand two important concepts: the Java object header and Monitor.
Java object header, monitor
Java object headers and monitor are the basis for implementing synchronized! The following is a detailed introduction of these two concepts.
Java object header
The locks used by synchronized are stored in the Java object header, so what is the Java object header? The object header of Hotspot virtual machine mainly includes two parts of data: Mark Word (tag field) and Klass Pointer (type pointer). Where Klass Point is the pointer of the object to its class metadata, the virtual machine uses this pointer to determine which class instance the object is, and Mark Word is used to store the object's own run-time data, which is the key to implementing lightweight locks and biased locks, so the following will focus on
Mark Word .
Mark Word is used to store the runtime data of the object itself, such as HashCode, GC generation age, lock status flag, locks held by threads, biased thread ID, biased timestamps, and so on. The Java object header generally holds two machine codes (in a 32-bit virtual machine, one machine code is equal to 4 bytes, that is, 32bit), but if the object is an array type, three machine codes are required, because the JVM virtual machine can determine the size of the Java object through the metadata information of the Java object, but cannot confirm the size of the array from the metadata of the array, so one block is used to record the length of the array. The following figure shows the storage structure of the Java object header (32-bit virtual machine):
Object header information is an additional storage cost independent of the data defined by the object itself, but considering the space efficiency of the virtual machine, Mark Word is designed as a non-fixed data structure to store as much data as possible in a very small space, and it reuses its own storage space according to the state of the object, that is, the Mark Word changes as the program runs, as follows (32-bit virtual machine):
After a brief introduction to the Java object header, let's take a look at Monitor.
Monitor
What is Monitor? We can understand it as a synchronization tool, or it can be described as a synchronization mechanism, which is usually described as an object.
Like all objects, all Java objects are born Monitor, and every Java object has the potential to become a Monitor, because in the design of Java, every Java object comes out of the womb with an invisible lock, which is called an internal lock or Monitor lock.
Monitor is a thread-private data structure, and each thread has a list of available monitor record, as well as a global available list. Each locked object is associated with a monitor (the LockWord in the MarkWord of the object header points to the starting address of the monitor), and there is an Owner field in the monitor that stores the * identity of the thread that owns the lock, indicating that the lock is occupied by the thread. Its structure is as follows:
Owner: initially NULL means that no thread currently owns the monitor record. The thread identity is saved when the thread successfully owns the lock, and is set to NULL when the lock is released.
EntryQ: associates a system mutex (semaphore) that blocks all failed threads trying to lock the monitor record.
RcThis: represents the number of all threads of blocked or waiting on this monitor record.
Nest: used to implement the count of reentrant locks.
HashCode: holds the HashCode value copied from the object header (and possibly GC age).
Candidate: used to avoid unnecessary blocking or waiting for threads to wake up, because only one thread can successfully own the lock at a time, and if each time the previous thread that released the lock wakes up all the threads that are blocking or waiting, it will cause unnecessary context switching (from blocking to ready and then blocked due to competitive lock failure), resulting in serious performance degradation. Candidate has only two possible values of 0 to indicate that there is no thread 1 that needs to be woken up means to wake up a successor thread to compete for locks.
Excerpt from: implementation principle and Application of synchronized in Java)
We know that synchronized is a heavyweight lock with low efficiency, and this idea has always been in our minds, but the implementation of synchronize has been optimized in jdk 1.6 to make it seem less heavy, so what optimizations have been used by JVM?
Lock optimization
Jdk1.6 introduces a lot of optimization to the implementation of lock, such as spin lock, adaptive spin lock, lock elimination, lock coarsening, bias lock, lightweight lock and so on to reduce the cost of lock operation.
There are four main states of locks, which are: no lock state, partial lock state, lightweight lock state and heavy lock state, which will be upgraded gradually with the fierce competition. Note that locks can be upgraded and cannot be degraded, and this strategy is to improve the efficiency of acquiring and releasing locks.
Spin lock
Thread blocking and awakening requires CPU to change from user mode to kernel mentality. Frequent blocking and awakening is a heavy task for CPU, which is bound to bring great pressure to the concurrent performance of the system. At the same time, we find that in many applications, the lock state of object locks only lasts for a short period of time, so it is not worthwhile to block and wake up threads frequently in this short period of time. So spin locks are introduced.
What is spin lock?
The so-called spin lock is to let the thread wait for a period of time without being suspended immediately to see if the thread holding the lock will release the lock quickly. How do you wait? Just execute a meaningless loop (spin).
Spin waiting is no substitute for blocking, not to mention the requirement for the number of processors (multi-core, there seems to be no single-core processor now). Although it can avoid the overhead of thread switching, it takes up processor time. If the thread holding the lock releases the lock quickly, then the spin efficiency is very good, on the contrary, the spinning thread will consume the processing resources in vain, and it will not do any meaningful work, typically occupying the manger. This will lead to a waste of performance. Therefore, the spin wait time (the number of spins) must have a limit, and if the spin exceeds the defined time and still does not acquire the lock, it should be suspended.
Spin locks are introduced in JDK 1.4.2 and are off by default, but can be turned on with-XX:+UseSpinning and on by default in JDK1.6. At the same time, the default number of spins is 10, which can be adjusted by parameter-XX:PreBlockSpin.
If the spin number of the spin lock is adjusted by the parameter-XX:preBlockSpin, it will bring a lot of inconvenience. If I adjust the parameter to 10, but many threads in the system release the lock as soon as you exit (if you spin the lock once or twice more), would you be embarrassed? So JDK1.6 introduces adaptive spin locks to make virtual machines smarter and smarter.
Adaptive spin lock
JDK 1.6introduces a smarter spin lock, namely adaptive spin lock. The so-called adaptive means that the number of spins is no longer fixed, it is determined by the spin time of the previous time on the same lock and the state of the lock's owner. How does it do it? If the thread spins successfully, it will spin more times next time, because the virtual machine thinks that since it was successful last time, the spin is likely to succeed again, so it will allow the spin to wait for more times. On the other hand, if few spins are successful for a lock, the number of spins will be reduced or even omitted in the future, so as to avoid wasting processor resources.
With the adaptive spin lock, with the continuous improvement of program operation and performance monitoring information, the virtual machine will predict the status of the program lock more and more accurately, and the virtual machine will become more and more intelligent.
Lock elimination
In order to ensure the integrity of the data, we need to synchronously control this part of the operation, but in some cases, JVM detects that there can be no shared data competition, which is that JVM will eliminate these synchronous locks. Lock elimination is based on the data support of escape analysis.
If there is no competition, why do you need to lock it? So lock elimination can save time for meaningless lock requests. Whether the variable escapes or not needs to be determined by data flow analysis for the virtual machine, but is it not clear to us programmers? Will we add synchronization before blocks of code that clearly know there is no data competition? But sometimes the program is not what we think it is? Although we do not show the use of locks, there will be invisible locking operations when we use some of JDK's built-in API, such as StringBuffer, Vector, HashTable, etc. For example, StringBuffer's append () method, Vector's add () method:
12345678public void vectorTest () {Vector vector = new Vector (); for (int I = 0; I
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.