关于 Synchronized 关键字,这篇文章写的是非常清楚了: [Java 并发]深入浅出 synchronized 与锁
Synchronized 是可重入锁,今天这篇文章就通过代码直观展示下它的可重入特性
在展示之前,我们再来强调一下,什么是可重入: 可重入就是在使用 Synchronized 时,当一个线程得到一个对象锁之后,再次请求这个对象锁时是可以再次得到该对象的锁的
那么在一个 Synchronized 方法/块 的内部调用这个类的其他 Synchronized 方法/块 时,是可以得到锁的
用代码直观展示一下:
/**
* @introduce: 验证 synchronized 是可重入锁
* @author: zll
* @DATE: 2022-3-20 17:28:34
**/
public class SynchronizedService {
synchronized public void serviceOne(){
System.out.println("service one");
serviceTwo();
}
synchronized public void serviceTwo(){
System.out.println("service two");
serviceThree();
}
synchronized public void serviceThree(){
System.out.println("service three");
}
}
/**
* @introduce: 验证 synchronized 是可重入锁
* @author: zll
* @DATE: 2022-3-20 17:28:34
**/
public class ThreadRun extends Thread {
@Override
public void run(){
SynchronizedService synchronizedService = new SynchronizedService();
synchronizedService.serviceOne();
}
}
/**
* @introduce: 验证 synchronized 是可重入锁
* @author: zll
* @DATE: 2022-3-20 17:28:34
**/
public class Run {
public static void main(String[] args) {
ThreadRun thread = new ThreadRun();
thread.start();
}
}
在 SynchronizedService
这个类中, 方法 serviceOne
调用了同样被 synchronized
修饰的 serviceTwo
,方法 serviceTwo
也是调用了同样被 synchronized
修饰的 serviceThree
方法
serviceOne
在运行时就获得了 SynchronizedService
对象的锁, 而在 serviceOne
内部,则调用了被 synchronized
修饰 serviceTwo
, 如果 synchronized
不是可重入锁的话,此时方法 serviceTwo
也会去获取 SynchronizedService
对象的锁,但是 SynchronizedService
这个锁在被 serviceOne
占用着,也就是: 如果 synchronized
不是可重入锁的话,就会造成死锁
我们看下程序运行的结果
方法 serviceOne
, serviceTwo
, serviceThree
里的内容都打印了出来,说明没有造成死锁
也就是: synchronized
是可重入锁
扩展: synchronized 也支持父子类继承
如果父子类都是使用 synchronized
修饰的,那么它也是支持父子类继承的
来看个具体的例子:
/**
* @introduce: 验证 synchronized 支持父子类继承
* @author: zll
* @DATE: 2022-3-20 17:59:29
**/
public class MainService {
public int i = 10;
synchronized public void operateMainMethod(){
try {
i --;
System.out.println("main service print i = " + i);
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
/**
* @introduce: 验证 synchronized 支持父子类继承
* @author: zll
* @DATE: 2022-3-20 17:59:44
**/
public class SubService extends MainService{
synchronized public void operateSubMethod(){
try {
while ( i > 0){
i --;
System.out.println("sub service print i = " + i);
Thread.sleep(100);
this.operateMainMethod();
}
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
/**
* @introduce: 验证 synchronized 支持父子类继承
* @author: zll
* @DATE: 2022-3-20 17:59:52
**/
public class ThreadService extends Thread {
@Override
public void run(){
SubService subService = new SubService();
subService.operateSubMethod();
}
}
/**
* @introduce: 验证 synchronized 支持父子类继承
* @author: zll
* @DATE: 2022-3-20 18:00:00
**/
public class TestInherit {
public static void main(String[] args) {
ThreadService threadService = new ThreadService();
threadService.run();
}
}
同样的道理我在这里就不重复说了,直接看程序运行结果:
可以很清楚的看到, synchronized
是支持父子类继承的~
参考:
- Java 多线程编程核心技术
以上,
感谢您的阅读~