6

[Java 并发] Synchronized 不是可重入锁吗?能不能直观展示下?

 3 years ago
source link: https://www.dynamic-zheng.com/posts/9e1fd16f.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

[Java 并发] Synchronized 不是可重入锁吗?能不能直观展示下?

发表于

2021-03-27

| 分类于 Java 并发

| 评论数: 0

关于 Synchronized 关键字,这篇文章写的是非常清楚了: [Java 并发]深入浅出 synchronized 与锁

Synchronized 是可重入锁,今天这篇文章就通过代码直观展示下它的可重入特性

在展示之前,我们再来强调一下,什么是可重入: 可重入就是在使用 Synchronized 时,当一个线程得到一个对象锁之后,再次请求这个对象锁时是可以再次得到该对象的锁的
那么在一个 Synchronized 方法/块 的内部调用这个类的其他 Synchronized 方法/块 时,是可以得到锁的

用代码直观展示一下:

/**
* @introduce: 验证 synchronized 是可重入锁
* @author: zll
* @DATE: 2021-3-14 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: 2021-3-14 17:28:34
**/
public class ThreadRun extends Thread {
@Override
public void run(){
SynchronizedService synchronizedService = new SynchronizedService();
synchronizedService.serviceOne();
}
}

/**
* @introduce: 验证 synchronized 是可重入锁
* @author: zll
* @DATE: 2021-3-14 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:
**/
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:
**/
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:
**/
public class ThreadService extends Thread {
@Override
public void run(){
SubService subService = new SubService();
subService.operateSubMethod();
}
}

/**
* @introduce: 验证 synchronized 支持父子类继承
* @author: zll
* @DATE:
**/
public class TestInherit {
public static void main(String[] args) {
ThreadService threadService = new ThreadService();
threadService.run();
}
}

同样的道理我在这里就不重复说了,直接看程序运行结果:
在这里插入图片描述

可以很清楚的看到, synchronized 是支持父子类继承的~

  • Java 多线程编程核心技术

以上,
感谢您的阅读~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK