Synchronized is a very important keyword in Java.
1. Origins
There will always be generated transaction-specific reasons, the following code as an introduction to the lead Synchronized
public class SynchronizedDemo implements Runnable { private static int count = 0; public static void main(String[] args) { for (int i = 0; i < 10; i++) { Thread thread = new Thread(new SynchronizedDemo()); thread.start(); } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("result: " + count); } @Override public void run() { for (int i = 0; i < 1000000; i++) count++; } }
10 threads simultaneously operating count, each thread do a million times count increment operator, the final result is not necessarily out of a million, and the results of each run is not the same.
2. Synchronized implementation principle
The principle: JVM through the entry, exit, an object monitor (Monitor) method to achieve synchronization sync block.
Look at the following piece of code
public class SynchronizedDemo { public static void main(String[] args) { synchronized (SynchronizedDemo.class) { } method(); } private static void method() { } }
After compilation, see the bytecode file with javap -v SynchronizedDemo.class:
This can be seen, any thread access to the Object, we must first get Object monitor, if the acquisition fails, the thread enters the synchronized state, the thread state to BLOCKED, when the Object monitor occupants release, in sync queue thread will have the opportunity to reacquire the monitor.
3. lock acquisition and lock release semantic memorypublic class MonitorDemo { private int a = 0; public synchronized void writer() { // 1 a++; // 2 } // 3 public synchronized void reader() { // 4 int i = a; // 5 } // 6 }
As can be seen from the figure, the thread A first reads the value of the shared variable a = 0 to start the main memory and then copied to the variable own local memory, an operation performed after the addition, then the value is flushed to main memory , the entire process is known lock thread a -> execute a critical section of code -> lock release corresponding memory semantics.
Thread B to acquire the lock time will be equally shared main memory from the value of variable a, this time is the latest value of 1, the value is then copied to the working memory thread B's go, release the lock when the same will be rewritten to the main memory.
On the whole, the results of execution of thread A (a = 1) are visible on thread B, implementation principle is: the lock is released when the values are flushed to main memory, the main forces from the memory when another thread to acquire the lock get the latest value.
From the horizontal point of view, it is like a thread A communicate via shared variables in main memory and thread B, A tells B the two of us shared data is now a matter, communication mechanism between the threads of this coincided exactly java memory model concurrent shared memory model structure.
3.1.1 What is CAS?
When using the lock, the thread acquires the lock is a pessimistic locking strategy , which assumes that each execution of a critical section of code can create conflicts, so the current thread to acquire the lock time will also block other threads to acquire the lock. The CAS operation (also known as lock-free operations) is an optimistic locking strategy , when it is assumed that all the threads access to shared resources does not conflict, since the conflict does not occur naturally does not block operation of the other threads. Therefore, the thread does not block pause state occurs. So, if there was a conflict how to do? No lock operation is to use ** CAS (compare and swap) ** aka thread compare exchange to identify whether there is a conflict, the conflict appeared to retry the current operation until there is no conflict.
Process 3.1.2 CAS operations
CAS exchange comparison process may be understood as popular CAS (V, O, N) , three values are: an actual value V stored in the memory address; new updated value of N; O expected value (old value) . When V and O are the same, that is to say the old value and the actual value of the same memory indicates that the value has not been changed by another thread before, that is, the old value O is for now the latest value, and naturally the new value of N can be assigned to V. On the contrary, V and O are not the same, indicating that the value has been another thread to turn over the old value of O is not the latest version of the value, so you can not assign a new value V N, V can be returned. When multiple threads using a CAS operating variable is, only one thread will be successful, and successful update, the rest will fail. The thread will try again failed, of course, can choose to suspend a thread
CAS implementation requires hardware instruction set support, after JDK1.5 virtual machine to be provided by the processor using the CMPXCHG instructions.
3.1.3 CAS issues
1. ABA problem because the CAS will check the old values have not changed, there is an interesting question here. For example, an old value to the A to the B, and then into A, just do the old value and CAS examination revealed no change still is A, but in fact did change. Solutions can follow common database optimistic locking way, add a version number can be resolved. The original path changes A-> B-> A becomes 1A-> 2B-> 3C. java language so good, of course, provide the atomic java package after 1.5 in the ABA AtomicStampedReference to solve the problem, the idea is to solve the case.
2. spin too long
Non-blocking synchronization using CAS, that is not the thread is suspended, it will spin (nothing more than an endless loop) were the next attempt, if the spin here too long on performance is a big consumption. If the JVM can support pause instructions provided by the processor, so there will be some improvement in efficiency.
3. atomic operation can only guarantee a shared variable
When performing operations on a shared variable that can guarantee atomicity CAS, if the operation of a plurality of shared variables, CAS can not guarantee atomicity. There is a solution is to use an object to integrate multiple shared variables, namely a class member variable is these shared variables. This object is then done CAS operation can guarantee atomicity. atomic AtomicReference provided to ensure that the object between the reference atom.
3.2 Java object header
As shown by default information is stored hasdcode, the age and value of the lock flag like Mark Word.
Java SE 1.6, the lock There are four kinds of state-level from low to high are: lock-free status, tend to lock status, lock status lightweight and heavyweight lock state , these states will be gradually upgraded with competition . Lock can upgrade but can not downgrade means that bias can not be downgraded to a biased locking the lock upgrade to a lightweight lock. This lock upgrade but can not downgrade strategy is designed to improve efficiency and get the lock to release the lock. MarkWord object changes as following:
3.2 biased locking
HotSpot author has found that, in most cases, there is no multi-threaded lock not only competitive, but always get many times by the same thread, a thread to acquire a lock in order to allow lower costs and the introduction of bias lock.
Figure 1 shows a thread under the process of obtaining biased locking thread 2 illustrates the process biased locking revocation.
How to turn off biased locking
3.5 Comparison of various locks
Author: Listen ___
link: https: //juejin.im/post/5ae6dc04f265da0ba351d3ff