The basic use

  1. Synchronized is placed on the instance method, and the lock object is the current this object
  2. Synchronized is placed on class methods (static methods), and lock objects are class objects in the method area
  3. Synchronized modifies a block of code, also known as synchronized(object){}, where the lock object is an object in ()

Synchronized keeps threads synchronized with the ACC_SYNCHRONIZED identifier when synchronized is used to modify methods.

Synchronized is used to modify code blocks through the Monitorenter and Monitorexit directives

Realize the principle of

  • Code level, Synchronized keyword.

  • At JAVA bytecode level, the synchronization method is defined by ACC_SYNCHRONIZED modification, and the synchronization code block is implemented by monitorenter and Monitorexit instructions.

  • At the JVM level, no locks, biased locks, lightweight locks, heavyweight locks.

  • Operating system level is called assembly instruction LOCK CMPXCHG, through lock to ensure that the following command (CMPXCHG) can only be executed by one thread.

  • At the hardware level, a northbridge semaphore is locked.

1) CPMXCHG

  • Used to compare and swap operands. CPU supports CAS primitives
  • Non-atomic, originally used in single-core cpus

2) LOCK prefix

  • The CPU guarantees the atomicity of the instructions it modifies

  • Disallow reordering

  • The cache is flushed to memory

With what?

1. Mark Word in the object header

Biased locking

ifLock flag bit ==01) {if(The bias marker is1) {Yes biased lock and biased Boolean Result of CAS operation = CAS operation replaces the ID of biased thread with that of the current threadif(CAS operation result == successful) {the current thread acquires the lock and executes the synchronized code block}else{CAS operation failed start [partial lock reversion] {wait until global safe pointvarStatus = Checks the state of the thread that originally held the lockif(status = = terminated | | has withdrawn from synchronization code area) the original thread releases the lock The current thread to acquire the lockelse if(status == runnable && not out of sync code area) {process of performing [partial lock balloons to lightweight locks] {thread stack that originally holds the lock 幁 allocate lock record, replace MarkWord and point to object address, perform synchronization code block, CAS release lock process of current thread executing lightweight lock { CAS spinif(spins a certain number of times without acquiring the lock) {inflate to the heavyweight lock}}}}}}}else {
        goto line 4Performing CAS operations}}else{not bias lock}Copy the code

Lightweight lock

ifLock flag bit ==00) {is the preemption of the lightweight lock to perform the lightweight lock. {the current thread's stack 幁 allocates the lock record, which consists of two parts, Copy the function of the product where the product is herbier and the onwer pointer points to the CAS for modifying the product of the product where the product is herbier and the onwer pointer points to the CAS for modifying the product of the product where the product is herbier Make the pointer to thread lock record field point to the current threadif(CAS operation successful) {current thread holds lock}else{CAS operation failed CAS spinif(spin beyond a certain number of times without success) {upgrade to heavyweight lock {change Markword to suspend the current thread}}}}}else{not lightweight lock}Copy the code

2. Monitor Monitor object

In Java, each object implicitly exists an object called monitor(object monitor), monitor object exists in the Java object header Mark Word, the source of this object is realized by C++

 class ObjectMonitor {.ObjectMonitor() {
    _header       = NULL; //markOop object header
    _count        = 0;    
    _waiters      = 0.//Number of waiting threads
    _recursions   = 0;   //Thread reentry times
    _object       = NULL;  //Store Monitor object
    _owner        = NULL;  //Thread to get ObjectMonitor object
    _WaitSet      = NULL;  //List of threads in wait state
    _WaitSetLock  = 0 ; 
    _Responsible  = NULL ;
    _succ         = NULL ;
    _cxq          = NULL ;	// One way list
    FreeNext      = NULL ;
    _EntryList    = NULL ; //Thread waiting for lock BLOCKED
    _SpinFreq     = 0 ;   
    _SpinClock    = 0 ;
    OwnerIsThread = 0 ; 
    _previous_owner_tid = 0; //ID of the previous owning thread of the monitor}...Copy the code

process

Thanks: Jacksgong

Lock the reentrant

  • Lock-biased reentrant

    • Simply identify the biased thread ID in Mark Word
  • Lock reentrant for lightweight locks

    • Add the lock record again, but displaed markword is null

    • Determine the number of reentries by the number of lock records

    • At the high end is the first lock record

  • Lock reentrant for heavyweight locks

    • Operating system to achieve