In the actual development, often need to consider the security of data concurrency issues, such as spike business scenarios, ticket business scenarios need to be considered concurrent, Java provides the Synchornize
key to solve the concurrency problem for us .
This article explains Synchornize
how keywords work
A, Java object header and Monitor
JVM, object layout in memory is divided into three areas: the first objects, instance data, and alignment padding.
- Examples of variables : storing attribute information such as data, attribute information including the parent class, instance if it is part of an array, the array also includes a length, a four-byte aligned memory.
- Padding data : the start address of the target virtual machine requirements must be an integer multiple of 8 bytes, stuffing data
不是必须
is present, only for byte alignment.
Java objects are to achieve the first Synchornize
base keyword, in general, Synchornize
the lock object is stored in advance in the JAVA object, the JVM uses 2 bytes to store object header (if the object is an array, assigned 3 bytes, left a byte is used to record the length of the array), and the main structure of Word Class MetaData Address mark composition
wherein the object is stored mark Word default HashCode, generational age lock flag etc. the following JVM 32, mark Word default storage structure
because the header information of the object with the object itself is defined in the data additional storage costs not related, and therefore the space efficiency is considered the JVM Mark Word
is designed to be a non-fixed data structures to store data more effectively, it based on the state of the object itself multiplexed own storage space, such as under the JVM 32, in addition to those listed above Mark Word
to the default storage structure, as well as possible changes in the structure of
which is biased locking locks and lightweight Java 6 pair of synchronized
locks after optimization of the new increase, we will briefly analyze later. Here we analyze the heavyweight lock is often said that synchronized
the object lock, the lock flag 10, which is a pointer to monitor
an object (also referred to as tube-monitor or lock) the start address. Each object there is an monitor
associated, objects and their monitor
relationship between the presence of a variety of implementations, such as monitor
can be created or destroyed together with the object automatically generated when a thread attempts to acquire the object lock, but when one monitor
is holding a thread there after, it will be in a locked state
Monitor
In fact, a synchronization tool, it can be said to be a synchronization mechanism. His main features are:
- All methods of an object are "mutually exclusive" of execution. Monitor only one run like a "license", as a thread enters any one of the methods required to obtain this "permission" to leave the license return
- Usually provide singal mechanism: allows positive hold "permission" to temporarily give up the threads "permission", waiting for a true predicate (condition variable), and the condition is satisfied, the current process may "inform" the thread is waiting for the condition variable, so that he could run again to get permission
Second, the realization of the monitor
In the Java Virtual Machine (HotSpot) in, Monitor is implemented based on C ++, implemented by ObjectMonitor, the main data structure is as follows
ObjectMonitor() {
_header = NULL;
_count = 0;
_waiters = 0,
_recursions = 0;
_object = NULL;
_owner = NULL;
_WaitSet = NULL;
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ;
FreeNext = NULL ;
_EntryList = NULL ;
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}
ObjectMonitor There are several key attributes:
- _owner : pointing to an object thread holds ObjectMonitor
- _WaitSet : store thread queue in wait state
- _EntryList : stored in a waiting queue of threads that lock block
- _recursions : the number of re-entry lock
- _count : used to record the number of times the thread to acquire a lock
When multiple threads access synchronization code section will first enter the _EntryList
queue, a thread obtained when the object monitor
into the _Owner
region and to monitor
the _owner
variable is set to the current thread, while monitor
the counter _count
is incremented. That obtain the object lock
when held by monitor
the calling thread wait()
method, will release the currently held monitor
, _owner
variable recovery is null
, _count
from minus 1, while the thread into the _WaitSet
collection waiting to be awakened. If the current thread is finished will be released monitor
(latch) and resets the value of the variable, so that other thread enters acquire monitor
(lock) monitor
(pointer stored) objects exist in the object header of each Java object, the synchronized
lock is in this way to acquire the lock, is why any object in Java can be used as a reason for the lock, but also notify/notifyAll/wait
other methods exist in the top-level objects in the Object reasons, the use of these three methods, must be in the synchronized
code block or synchronized
method, otherwise it will throw an IllegalMonitorStateException
anomaly, because before calling these methods must get the current monitor object monitor
objects, that notify/notifyAll
and the wait
method relies on monitor
the object
Three, Synchornize keyword works
JVM through entry and exit monitor
to implement monitor method, the sync block synchronization, particularly after it is compiled in the preamble of the method call monitor.entry
instruction, plus a place to exit and unusual monitor.exit
instructions, essentially on a monitor object (monitor) be acquired, and this acquisition is exclusive, so as to achieve the purpose can only be accessed by a thread. For those who did not get a thread lock will block the entrance to the methods, until that thread to acquire a lock executed monitor.exit
after the instructions before attempting to acquire lock again
through code demonstrates:
/**
* @author Gjing
**/
public class Test {
public void test() {
synchronized (this) {
System.out.println("hello");
}
}
}
By javap -c Test.class
command View assembly instruction
Compiled from "Test.java"
public class com.gj.Test {
public com.gj.Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public void test();
Code:
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #3 // String hello
9: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: aload_1
13: monitorexit
14: goto 22
17: astore_2
18: aload_1
19: monitorexit
20: aload_2
21: athrow
22: return
Exception table:
from to target type
4 14 17 any
17 20 17 any
}
Contain fast synchronization may be seen inlet and epilogue monitorentry
and monitorexit
instructions
Fourth, the biased locking, lightweight lock
synchronize
Many are called lock by weight, of the of JDK1.6 synchronize
conducted various optimization, in order to reduce the consumption of acquiring and releasing locks brought introduces biased locking lock and lightweight
1, biased locking
In order to further reduce the cost to acquire the lock, after JDK1.6 also introduces bias lock. Biased locking of 特征
the main lock is multi-threaded competition does not exist, and should be a thread has won lock
To obtain the lock process :
1, the biased locking Mark Word access identifier is set to a 1, whether the lock flag 01, it was confirmed to be biased state.
2, if that can be biased state, the test thread ID is pointing to the current thread, and if so, proceed to step 5. Otherwise, proceed to step 3.
3, if the thread ID is not pointing to the current thread, CAS operations competing lock through. If the competition is successful, Mark Word thread ID is set to the current thread ID, then perform 5; if competition fails to perform 4.
4, if the CAS obtain biased locking fails, then there is competition. Biased locking thread gets when reaching the global security point (safepoint) is suspended, biased locking upgraded to lightweight lock, then blocked at the point of thread-safe synchronization code continues down. (Revocation biased locking time will lead to stop the word)
5, the synchronization code execution.
Unlock :
When there is another thread gets the lock, the lock will tend to hold the thread releases the lock, will wait for global security point (the moment there is no bytecode operation) is released, then pauses the thread that owns the lock bias, according to the lock object is currently locked to determine whether the head object is set to Mark Word no lock or lock state is lightweight. Lightweight lock synchronization can improve program performance did not compete with, but if the program exists in most of the locks are competitive, that tend to lock will not achieve much effect. It can be used
-XX:-userBiasedLocking=false
to close the bias lock and enter the default lock lightweight
Applicable scene :
Always only one thread executing synchronized block, it has not been executed before the release of the lock, no other thread to perform synchronization block, no competition in the lock case, once you have upgraded to compete lightweight locks, upgraded light revocation of the order when the need to lock the lock biased, biased locking revoked when the operation will lead to stop the word; when there is competition in the lock, the lock will tend to do a lot of extra operations, especially in favor of the revocation time will result in safe point safety point will lead stw, degraded performance, you should disable this case
2, the lock Lightweight
Lightweight lock is biased to the lock escalation, biased locking operation in case of a thread enters a synchronized block when the second thread to join lock contention, lock bias will be upgraded as a lightweight lock
Acquire a lock process :
1, when the code entered sync blocks, if the synchronization object is a non-lock state, the current thread creates a stack frame
锁记录(Lock Record)区域
, while the object header locks the object ofMark Word
copying the lock record, and then attempt to useCAS
theMark Word
updated to point to the lock pointer record.2, if the update is successful, the current thread to get a lock.
3. If the update fails JVM will check the lock object
Mark Word
points to the locks on the current thread.4, if the lock is then the current thread owns the lock object, you can directly enter the synchronized block. Not then there is another thread to seize the lock, if multiple threads at the same time there is a competing lock, the lock will be lightweight
膨胀为重量锁
Unlock :
Unlocking process is the use of lightweight lock
CAS
is achieved, it will try to replace the locks lock back objectMark Word
. If successful it means replacing the entire synchronization is complete, fail then there is another thread attempts to acquire a lock, then it will wake suspended thread (this time has been expanded to weight lock) reasons lightweight locks can improve performance are: think most locks are not competing in the entire synchronization cycle, so useCAS
less overhead than mutually exclusive. But if the lock fierce competition, lightweight lock is not only mutually exclusive overhead, as well asCAS
overhead, even slower than the weight of the lock
This concludes the article, if there are any errors point to be noted in the comments below