什么是可重入?可重入锁?
可重入:(来源于维基百科)若一个程序或子程序可以“在任意时刻被中断然后操作系统调度执行另外一段代码,这段代码又调用了该子程序不会出错”,则称其为可重入(reentrant或re-entrant)的。即当该子程序正在运行时,执行线程可以再次进入并执行它,仍然获得符合设计时预期的结果。与多线程并发执行的线程安全不同,可重入强调对单个线程执行时重新进入同一个子程序仍然是安全的。
可重入锁:又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。
看如下的例子
public class SynchronizedDemo {
public static void main(String[] args) {
SynchronizedDemo demo = new SynchronizedDemo();
demo.method1();
}
private synchronized void method1() {
System.out.println(Thread.currentThread().getId() + ": method1()");
method2();
}
private synchronized void method2() {
System.out.println(Thread.currentThread().getId()+ ": method2()");
method3();
}
private synchronized void method3() {
System.out.println(Thread.currentThread().getId()+ ": method3()");
}
}
结合前文中加锁和释放锁的原理,不难理解:
执行monitorenter获取锁
(monitor计数器=0,可获取锁)
执行method1()方法,monitor计数器+1 -> 1 (获取到锁)
执行method2()方法,monitor计数器+1 -> 2
执行method3()方法,monitor计数器+1 -> 3
执行monitorexit命令
method3()方法执行完,monitor计数器-1 -> 2
method2()方法执行完,monitor计数器-1 -> 1
method2()方法执行完,monitor计数器-1 -> 0 (释放了锁)
(monitor计数器=0,锁被释放了)
这就是Synchronized的重入性,即在同一锁程中,每个对象拥有一个monitor计数器,当线程获取该对象锁后,monitor计数器就会加一,释放锁后就会将monitor计数器减一,线程不需要再次获取同一把锁。
------
原文链接:https://pdai.tech/md/java/thread/java-thread-x-key-synchronized.html
|