Synchronized use and simple analytical

Synchronized use and simple analytical

1. usage scenarios:

When multiple threads concurrently operate on the same critical resources, we will find that the code is not synchronized, resulting in results may be beyond our expectations. For example, the following example:


public class Async implements Runnable {
	
	//临界变量
	static int i=0;
	
 public static void increase()
	{
		for(int i=0;i<5;i++)
		{
			System.out.print(i);
		}
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		increase();
	}
	
	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		
		Async async = new Async();
		Async async2 = new Async();
		
		Thread thread1 = new Thread(async);
		Thread thread2 = new Thread(async2);
		
	
		thread1.start();
		thread2.start();
		thread1.join();
		thread2.join();
		//join 表示将当前线程执行完毕后再返回线程
	}
/*
每次运行的结果是随机的
*/

}

Running this code we can find is not the same result every time the code execution. This is the result threads are not synchronized. And if we want to become the code synchronization, you need to lock.
The locked mode is very simple, just add a keyword on the increase () method: the synchronized can be.
as follows:

synchronized public static void increase()
	{
		for(int i=0;i<5;i++)
		{
			System.out.print(i);
		}
	}

2. Classification

The next one will be synchronized case is divided into two categories. One is the object lock, lock, and class.
Object lock the lock object, java object header information Mark Word field stores information on the lock.

3. Specific applications:

synchronized There are three main applications:

  • Examples of modified method, the current applied to the locking instance, before entering a synchronization code to obtain the current instance of the lock

  • Modification of static methods, the role of the current class object locking, before entering the lock synchronization code to obtain the current class object

  • Modifying the code block, designated lock object, to lock a given object, before entering the synchronization code library to obtain a given lock of the object.

Examples 3.1 Method applied:


public class Async implements Runnable {
	
	//临界变量
	static int n=0;
	
	 public synchronized  void increase()
	{
		for(int i=0;i<5;i++)
		{
			n++;
			System.out.print(n);
		}
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		increase();
	}
	

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		
		Async async = new Async();
		
		Thread thread1 = new Thread(async );
		Thread thread2 = new Thread(async );
		
	
		thread1.start();
		thread2.start();
		thread1.join();
		thread2.join();

	}

	

}

3.2 Modified static method:

When there are multiple objects in our code to access the same static resources, we need to lock the static resources.


public class Async implements Runnable {
	
	//临界变量
	static int n=0;
	
	 public synchronized static void increase()
	{
		for(int i=0;i<5;i++)
		{
			n++;
			System.out.print(n);
		}
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		increase();
	}
	

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		
		Async async = new Async();
		Async async2 = new Async();
		
		Thread thread1 = new Thread(async );
		Thread thread2 = new Thread(async2 );
		
	
		thread1.start();
		thread2.start();
		thread1.join();
		thread2.join();

	}

	

}

3.3 Specify a modified code blocks:

When our method is too large, but the block of code need to be synchronized only a small part of the time, we only want to add synchronization lock on the synchronized block of code, as follows:


public class Async implements Runnable {
	
	private static Async async = new Async();
	
	//临界变量
	static int n=0;
	

	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		synchronized(this)//this指代async 对象
		{
			for(int i=0;i<5;i++)
			{
				n++;
				System.out.print(n);
			}
		}
	}
	

	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		
		
		Thread thread1 = new Thread(async);
		Thread thread2 = new Thread(async);
		
	
		thread1.start();
		thread2.start();
		thread1.join();
		thread2.join();

	}

	

}

When using the block synchronization lock, we can pass the object you want to sync, or class object.

It is worth mentioning that, when the non-static synchronous lock, thread B calls the non-static synchronous lock when a thread A call that an object lock call, a call to class lock when the two locks are not mutually exclusive. At this time, it will produce thread-safety issues.

4. simple analytical

4.1Monitor

In the JVM, object layout in memory is divided into three areas: the first objects, instance data, and alignment padding.
In the object header, there is a field called Markdown, this field is of variable length. Which stores hashCode object lock information or age or generational GC signs and other information. Heavyweight locks stored in the information points to a monitor object (monitor object). java each object has a corresponding monitor object. When the monitor is held by a thread, the object will be in a locked state.

Java Virtual Machine (HotSpot) in, ObjectMonitor Monitor is implemented, the main data structure is as follows (in the HotSpot VM ObjectMonitor.hpp source files, C ++ implementation)

ObjectMonitor there are two queues, _WaitSet and _EntryList, to save ObjectWaiter object list (each thread will wait for the lock to be packaged objects ObjectWaiter), _ owner thread holds ObjectMonitor object point, when a plurality of threads simultaneously access the synchronization period when the code, enter _EntryList first set, when the thread enters the monitor object acquired _Owner monitor area and the owner is the current thread while the variable is set to monitor the count of the counter is incremented by 1 if the calling thread wait () method, the release currently held monitor, owner variable recovery is null, count from minus 1, while the thread enters WaitSe t set waiting to be awakened. If the current thread is finished will release the monitor (lock) and resets the value of the variable, so that other threads get into the monitor (lock). As shown below

Here Insert Picture Description

4.2 Method Lock:

The method of implicit synchronization stage, i.e. without controlled by the bytecode instructions it implements the method call and return in the operation. JVM if a method can be distinguished from the synchronization method of the method of the constant pool table structure ACC_SYNCHRONIZED method of access flags (method_info Structure) of. When the method is called, the call instruction will check whether the method of ACC_SYNCHRONIZED access flag is set, if set, execution thread will first hold monitor (using the term virtual machine specification is the tube), then perform the method, and finally another way to accomplish (both normal and non-normal completion or completion) time release monitor. During method execution, execution thread holds the monitor, no other thread can no longer obtain the same monitor. If a synchronization method throws an exception during execution, and can not handle this exception within the way, that this synchronization method held by the monitor will automatically released when an exception thrown outside the synchronization method.

5.Java optimization of virtual machine synchronized

There are four state of the lock, no lock status, tend to lock, lightweight and heavyweight lock lock. With the lock of the competition, you can upgrade from lock to lock biased lightweight lock, then upgrade heavyweight lock, but the lock escalation is unidirectional, that is to say only upgrade from low to high, the lock will not appear downgrade.

5.1 biased locking

Biased locking the main reference scenario is: In some cases, a lock most of the time will not be competing multiple threads simultaneously, but frequently been repeatedly held by the same thread. Biased locking core idea is that if a thread gets the lock, then the lock to enter bias mode, where Mark Word structure also becomes biased locking structure, when the thread again requesting a lock, and no further synchronization, namely the process of acquiring the lock, thus eliminating a large number of operations concerning the application of locks, which will provide the performance of the program. But when a resource is often preempted multiple threads when biased locking not for you. After biased locking failure, and will not expand immediately heavyweight lock, but the first upgrade to lightweight lock.

5.2 Lightweight lock

If tend to lock fails, the virtual machine will not immediately upgrade to heavyweight lock, it will try to optimize the use of a tool called a lightweight lock (after adding 1.6), then Mark Word structure also becomes light the order of the lock structure. Based on a lightweight lock can improve the performance of the program is "to most of the locks, there is no competition in the entire synchronization cycle," Note that this is empirical data. Need to understand that the lightweight lock the adaptation of the scene is performed alternately thread occasion sync block, if there is a lock to access the same occasion the same time, it will lead to the lightweight heavyweight lock lock inflation.

5.3 Spinlocks

After a lightweight lock fails, the virtual machine in order to avoid the real thread hangs in the operating system level, but also a means to optimize known as spin lock. This state is the need to convert from user-based, in most cases, the thread that holds the lock time will not be too long, if they are directly hung operating system-level thread may be wasted, after all, the operating system to switch between threads core state transitions between the state requires a relatively long period of time, the time cost is relatively high, so the spin lock will assume in the near future, the current thread can acquire the lock, so the opportunities for virtual threads that are currently want to get a lock do a few empty cycle (which is also known as the reasons spin), generally not too long, it may be 50 cycles or 100 cycles, after several cycles, if you get a lock, they successfully enter the critical region. If you can not get the lock, it will be the operating system level thread hangs, this is the way to optimize spin lock, indeed, in this way can improve efficiency. Finally, no way it can only be upgraded to heavyweight locked.

5.4 Lock elimination

Eliminating the lock is another virtual machine lock optimization, this optimization is more thorough, Java virtual machine JIT compile time (can be understood as a simple piece of code to be compiled when about to be executed for the first time, also known as real-time compilation), by scanning operation of the lock context, there can be no removal of the shared resource competition, eliminating this way the lock is not necessary, it can save time lock requests meaningless, as StringBuffer's append a synchronization method, but add in the way the StringBuffer belong to a local variable, and will not be used by other threads, so there can be no StringBuffer scene shared resource contention, JVM will automatically lock eliminated.

6.synchronized key points:

6.1

synchronized is reentrant, meaning When a thread holds the lock, again, when requested, will not be blocked.

6.2

When a thread interrupts, interrupt method calling thread instance of an object blocking the abnormal interruption and throws InterruptedException exceptions, the interrupt state will also be reset. So for a thread, if when the interrupt occurs, it is waiting for a lock that it will continue to wait for the lock. If a lock has been obtained, it will continue. So when we call interrupt () method, you must manually detect whether the thread is interrupted, and then make the appropriate treatment.

6.3

When the thread wakes up, awakening the statement must be synchronized block or synchronized method, otherwise it will throw an exception IllegalMonitorStateException This is because these methods must be called before to get the current monitor monitor target object, that is notify / notifyAll and wait methods depend on the monitor objects
and different methods of sleep is to wait after the method call completes, the thread will be suspended, but the wait method will release the current lock held by the monitor (monitor), until the thread calls notify / after notifyAll method can only continue, but only thread to sleep sleep method does not release the lock. While the rear notify / notifyAll method calls, and does not immediately release the lock monitor, but () {} / synchronized method is performed automatically release the lock only after the end of the respective synchronized.

Herein by reference: [https://blog.csdn.net/javazejian/article/details/72828483?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task]

Published 47 original articles · won praise 15 · views 10000 +

Guess you like

Origin blog.csdn.net/qq_41525021/article/details/104596262