Synchronized reentrancy and uninterruptibility analysis and code verification in Java

Introduction

This article introduces synchronizedtwo important properties of keywords, reentrancy and uninterruptibility, which we will implement and verify with code.

What is the use of understanding this theoretical nature?

Only when you understand the feature can you understand Synchronizedthe scope of action, and it is not easy to make mistakes when using it.

1. Reentrancy

可重入性:同一个线程的外层函数获得锁后,内层函数可以直接获取该锁。

Here's an example of reentrancy in life:

When we were queuing, we often encountered some uncivilized people who would let their friends cut directly to his place, and sometimes cut several at a time. This is that after a person obtains the priority, all those who rely on him will get the right. This is a manifestation of reentrancy.

1. Two advantages of Synchronized reentrancy:

  1. avoid deadlock

Reasons for avoiding deadlocks: If there synchronizedis no reentrancy, when a thread wants to access another method, it already holds a lock, and it has not released the lock, and wants to acquire the lock of another method, so A deadlock caused by waiting forever will cause deadlock. With reentrancy, you hold a lock yourself and can directly enter the inner function to avoid deadlock.

  1. Improve packaging

Programmers do not need to manually lock and unlock, and are managed by the JVM, which improves availability.

2. Granularity of Synchronized reentrancy (scope)

Synchronized可重入性的作用范围是整个获得锁的线程,线程内部的所有被调用的方法都共享该锁。

Which methods inside a thread share the same lock?

  • the same method in the same class
  • Different methods in the same class
  • methods in different classes

3. The code verifies the reentrancy of the above three cases

① The same method in the same class, verify reentrancy:

The purpose of the experiment is to call the same method recursively. If synchronizedthe modified method can call its own method recursively, it means that it has reentrancy in the synchronized method.

public class RecursiveLockCondition1 {

	//跳出递归的条件,需在递归方法外部声明,否则会造成死循环
	int i = 0;

	private synchronized void method() {
		System.out.println("递归调用:i=" + i);
		if (i == 0) {
			i++;
			//递归调用本方法
			method();
		}
	}


	public static void main(String[] args) {
		RecursiveLockCondition1 recursiveLockCondition1 = new RecursiveLockCondition1();
		recursiveLockCondition1.method();
	}
}

Results of the:

递归调用:i=0
递归调用:i=1

② Different methods in the same class to verify reentrancy:

Phenomenon: From a synchronized method, calling another synchronized method in the same class can be executed. Prove:

同一个类中,一个同步方法调用另一个同步方法,可重入性质依然存在。
public class RecursiveLockCondition2 {

	private synchronized void method1() {
		System.out.println("method1执行");
		method2();
	}

	private synchronized void method2() {
		System.out.println("method2执行");
	}

	public static void main(String[] args) {
		RecursiveLockCondition2 condition2 = new RecursiveLockCondition2();
		condition2.method1();
	}
}

Expected and actual results: method2() method is executed.

method1执行
method2执行

③Methods in different classes to verify reentrancy:

Using a subclass to call a synchronized method in a parent class proves that
calling a synchronized method in a different class is also reentrant.

public class RecursiveLockCondition3 {

	protected synchronized void method() {
		System.out.println("父类方法,被执行");
	}

}

// 子类
class ChildClass extends RecursiveLockCondition3 {

	@Override
	protected synchronized void method() {
		System.out.println("子类方法,被执行");
		super.method();
	}

	public static void main(String[] args) {
		ChildClass childClass = new ChildClass();
		childClass.method();
	}
}

Expected and actual results: The method() method of the parent class is also executed.

子类方法,被执行
父类方法,被执行

2. Uninterruptibility

definition:

当锁被别的线程获得以后,如当前线程想获得,只能等待或堵塞,直到其他线程释放了这个锁。如果其他线程不释放,当前线程会一直等待下去。

The code proves: synchronized is not automatically interrupted. That is, synchronized is uninterruptible.

Code simulation: If a thread that acquires a lock does not finish executing, another thread will wait forever.

public class UninterruptedCondition implements Runnable {

	static UninterruptedCondition instance = new UninterruptedCondition();

	@Override
	public void run() {
		method();
	}

	private synchronized void method() {
		//死循环:一直打印当前线程名
		while (true) {
			System.out.println("线程名:" + Thread.currentThread().getName() + ",正在执行");
		}
	}

	/**
	 * 
	 * 
	 */
	public static void main(String[] args) {
		Thread thread1 = new Thread(instance);
		Thread thread2 = new Thread(instance);
		thread1.start();
		thread2.start();
		while (thread1.isAlive() || thread2.isAlive()) {

		}
		System.out.println("执行结束");
	}
}

Expected and actual result: only one thread is printing, the other thread will wait forever.

线程名:Thread-1,正在执行
线程名:Thread-1,正在执行
线程名:Thread-1,正在执行
线程名:Thread-1,正在执行
线程名:Thread-1,正在执行
输出相同,省略...

Summarize

This article analyzes and proves the synchronizedreentrancy and uninterruptibility of keywords from the code level. Through these analysis, we mainly want to understand synchronizedthe scope of action and the waiting mechanism of locks. If these concepts are vague and uncertain in our minds Yes, when we use it, we often feel uneasy, because the problem in multi-threading sometimes cannot reach a certain amount of concurrency, even if there is an error, it cannot be found. If a problem is found, it will go wrong as soon as it goes online. Therefore, we must be clear about the execution mechanism and principle of these most commonly used concurrency tools, so that many problems can be avoided when coding. If you like this article, please like and subscribe.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324110727&siteId=291194637