Synchronized
used to lock objects and methods or blocks of code, when it locks a method or a block of code, at most one thread at a time executes the code. When two concurrent threads access the same object in the same lock synchronization code block, only one thread can be executed within a single time. The other thread must wait for the current thread to finish executing the block before it can execute the code block.
to understand the synchoronized principle, let's first talk about the layout of the object header part of the virtual machine (the hotspot as an example). The object header is divided into two pieces of information, the first part is used to store the object's own runtime data, such as HASHCODE,GC generational age, total 64 bits (64-bit virtual machine, 32-bit virtual machine 32-bit), officially become Mark Word, and another part of the object type pointer to the method area to store.
Normal Object Header
It is the normal object header, which is relative to the object that has the bias Lock (hereinafter). You can see a description of the 1bit bias lock in the object head, and a description of the 2bit lock. In the end is not 64 bits, we can pass unsafe (a very interesting class) to verify the following:
Public class cvolatile {private volatile boolean flag=false;//unsafe cannot be constructed directly, Get Public static unsafe getunsafe by Reflection () throws NoSuchFieldException, Securityexception, illegalargumentexception, illegalaccessexception{field field= Unsafe.class.getDeclaredField ("Theunsafe"); Field.setaccessible (true); Unsafe unsafe= (unsafe) field.get (null); return unsafe;} Public static void headerbyte () throws nosuchfieldexception, securityexception, illegalargumentexception, illegalaccessexception{unsafe unsafe=getunsafe (); Field field=cvolatile.class.getdeclaredfield ("flag"); System.out.println (Unsafe.objectfieldoffset (field));} public static void main (string args[]) throws Nosuchfieldexception, securityexception, illegalargumentexception, illegalaccessexcePtion{ headerbyte (); } }
above a new class that has only a Boolean variable and then gets the flag offset through unsafe, the console output is 8, indicating that the object header in the 64-bit JDK is indeed 8*8, which is 64bit.
The synchronization code block is through the monitorenter and Monitorexitand how does the JVM maintain the thread that competes with the same object lock, and the following is the process of posting all major blogs:
Contention List: All threads that request a lock will be placed first in the competition queue.
The threads in the Entry list:contention list that are eligible to be candidates are moved to the Entry list.
Wait set: Those threads that call the wait method are blocked and placed into the wait set.
OnDeck: There can be at most one line is impersonating at a competitive lock at any time, the thread is called OnDeck
Owner: The thread that acquired the lock is called owner.
The thread of the new request lock is first added to Conetentionlist, and when a thread that has a lock (owner state) calls unlock, the thread is moved from contentionlist to Entrylist if Entrylist is found to be empty. Contentionlist is a last-in-first-out queue, contentionlist is accessed concurrently by threads, and Entrylist is established to reduce contention for contentionlist tail. The owner thread migrates the thread from contentionlist to entrylist when unlock, and specifies that a thread in entrylist (typically head) is a ready (OnDeck) thread. The owner thread is not passing the lock to the OnDeck thread, but handing over the right to the competition lock to the Ondeck,ondeck thread requires a re-competition lock. The OnDeck thread obtains the lock and becomes the owner thread, and the inability to obtain the lock remains in the entrylist, and the position in the entrylist is not changed (still in the team header), given fairness. If the owner thread is blocked by the wait method, it is transferred to the Waitset queue, and if awakened at some point by Notify/notifyall, it is transferred to Entrylist again.
The most significant effect of a lock on the performance of a mutex-based synchronization is the implementation of blocking, where both the suspended thread and the recovery thread need to be loaded into the kernel state. At the same time, the locked state of the shared data will only last for a while, and it is not worthwhile to suspend and resume the thread for this period of time. If there are more than 1 processors on the physical machine, allowing 2 or 2 threads to execute simultaneously, we can let the thread that asks for the lock "wait a while", but not abandon the processor execution time, see if the thread holding the lock will release the lock soon, in order for the thread to wait, We let the thread perform a busy loop (which can be a few empty assembly instructions, execute several loops, or occupy the CPU), which is called a spin lock.
The synchronized thread enters the contentionlist with a spin attempt to obtain the lock, if it does not enter the waiting queue successfully. This is slightly unfair to those threads that are already waiting in the queue.
biased lock is to improve performance in the absence of competition in the case of the entire synchronization to cancel out. It will favor the first thread that gets it, and if no other thread competes for the lock during the next execution, the thread holding the lock never needs to be synchronized again. When the virtual machine enables a biased lock, when the lock object is first fetched by the thread, the virtual opportunity sets biased lock to 1 that is biased mode, while using CAs to write the thread ID of the lock to mark Word, if the CAS operation succeeds, the thread holding the lock enters the lock-related synchronization block. The virtual machine will not take any action.
The object header with a biased lock is successfully added
————————————————————— I'm a split line ——————————————————————
The fun unsafe class comes up again, and we can use unsafe to achieve a simple sychronized function.
Public static void csynchronized (Object syn) throws NoSuchFieldException, securityexception, illegalargumentexception, illegalaccessexception, interruptedexception{ Unsafe unsafe=getunsafe (); unsafe.monitorenter (SYN); for (int i=0;i<10;i++) {Thread.CurrentThread (). Sleep (100l); System.out.println (Thread.CurrentThread (). GetId ());} Unsafe.monitorexit (SYN);} public static void main (string args[]) { final object syn=new object (); new thread (new Runnable () {Public void run () { try {csynchronized (SYN);} catch (nosuchfieldexception e) {} catch (securityexception e) {} catch (illegalargumentexception e) {} catch (illegalaccessexception e) {} catch (interruptedexception e) &NBSP;{}}&NBSP;&NBSP;&NBSP;&Nbsp; }). Start (); new thread (New runnable () {public void run () { try {csynchronized (SYN);} catch (nosuchfieldexception e) {} catch (securityexception e) {} catch (illegalargumentexception e) {} catch (illegalaccessexception e) {} catch (interruptedexception e) {}} }). Start (); }
from the console results you can see that the thread ID is not interspersed, indicating that the synchronized basic functions are implemented. Of course, if we only keep the For loop in csynchronized, we can see that there are interspersed between the thread IDs.
——— synchronized first here, and then we're going to talk about lock.
Synchronized,reetrantlock and Volitale (i.)