Java, Synchornize key principles

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 Synchornizekey to solve the concurrency problem for us .

This article explains Synchornizehow 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.
jvm

  • 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 Synchornizebase keyword, in general, Synchornizethe 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
meta
wherein the object is stored mark Word default HashCode, generational age lock flag etc. the following JVM 32, mark Word default storage structure
basicMeta
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 Wordis 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 Wordto the default storage structure, as well as possible changes in the structure of
superMeta
which is biased locking locks and lightweight Java 6 pair of synchronizedlocks after optimization of the new increase, we will briefly analyze later. Here we analyze the heavyweight lock is often said that synchronizedthe object lock, the lock flag 10, which is a pointer to monitoran object (also referred to as tube-monitor or lock) the start address. Each object there is an monitorassociated, objects and their monitorrelationship between the presence of a variety of implementations, such as monitorcan be created or destroyed together with the object automatically generated when a thread attempts to acquire the object lock, but when one monitoris holding a thread there after, it will be in a locked state

MonitorIn 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 _EntryListqueue, a thread obtained when the object monitorinto the _Ownerregion and to monitorthe _ownervariable is set to the current thread, while monitorthe counter _countis incremented. That obtain the object lock
when held by monitorthe calling thread wait()method, will release the currently held monitor, _ownervariable recovery is null, _countfrom minus 1, while the thread into the _WaitSetcollection 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)
lock
monitor(pointer stored) objects exist in the object header of each Java object, the synchronizedlock 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/waitother methods exist in the top-level objects in the Object reasons, the use of these three methods, must be in the synchronizedcode block or synchronizedmethod, otherwise it will throw an IllegalMonitorStateExceptionanomaly, because before calling these methods must get the current monitor object monitorobjects, that notify/notifyAlland the waitmethod relies on monitorthe object

Three, Synchornize keyword works

JVM through entry and exit monitorto implement monitor method, the sync block synchronization, particularly after it is compiled in the preamble of the method call monitor.entryinstruction, plus a place to exit and unusual monitor.exitinstructions, 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.exitafter the instructions before attempting to acquire lock again
getlock
through code demonstrates:

/**
 * @author Gjing
 **/
public class Test {
    public void test() {
        synchronized (this) {
            System.out.println("hello");
        }
    }
}

By javap -c Test.classcommand 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 monitorentryand monitorexitinstructions

Fourth, the biased locking, lightweight lock

synchronizeMany are called lock by weight, of the of JDK1.6 synchronizeconducted 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=falseto 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 of Mark Wordcopying the lock record, and then attempt to use CASthe Mark Wordupdated 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 Wordpoints 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 CASis achieved, it will try to replace the locks lock back object Mark 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 use CASless overhead than mutually exclusive. But if the lock fierce competition, lightweight lock is not only mutually exclusive overhead, as well as CASoverhead, 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

Guess you like

Origin yq.aliyun.com/articles/708280