当前位置: 首页 > news >正文

JUC并发编程-8锁现象

5. 8锁现象

如何判断锁的是谁!锁到底锁的是谁?

锁会锁住:对象、Class

深刻理解我们的锁

问题1

两个同步方法,先执行发短信还是打电话

public class dome01 {public static void main(String[] args) {Phone phone = new Phone();	new Thread(() -> { phone.sendMs(); }).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone.call(); }).start();}
}class Phone {public synchronized void sendMs() {System.out.println("发短信");}public synchronized void call() {System.out.println("打电话");}
}
输出结果为发短信打电话

问题2:

我们再来看:我们让发短信 延迟4s

public class dome01 {public static void main(String[] args) throws InterruptedException {Phone phone = new Phone();new Thread(() -> {try {phone.sendMs();} catch (InterruptedException e) {e.printStackTrace();}}).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone.call(); }).start();}
}class Phone {public synchronized void sendMs() throws InterruptedException {TimeUnit.SECONDS.sleep(4);System.out.println("发短信");}public synchronized void call() {System.out.println("打电话");}
}
结果:还是先发短信,然后再打电话!

原因:并不是顺序执行,而是synchronized 锁住的对象是方法的调用!对于两个方法用的是同一个锁,谁先拿到谁先执行,另外一个等待

问题三

加一个普通方法

public class dome01 {public static void main(String[] args) throws InterruptedException {Phone phone = new Phone();new Thread(() -> {try {phone.sendMs();} catch (InterruptedException e) {e.printStackTrace();}}).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone.hello(); }).start();}
}class Phone {public synchronized void sendMs() throws InterruptedException {TimeUnit.SECONDS.sleep(4);System.out.println("发短信");}public synchronized void call() {System.out.println("打电话");}public void hello() {System.out.println("hello");}
}
输出结果为hello发短信

原因:hello是一个普通方法,不受synchronized锁的影响,不用等待锁的释放

问题四

如果我们使用的是两个对象,一个调用发短信,一个调用打电话,那么整个顺序是怎么样的呢?

public class dome01 {public static void main(String[] args) throws InterruptedException {Phone phone1 = new Phone();Phone phone2 = new Phone();new Thread(() -> {try {phone1.sendMs();} catch (InterruptedException e) {e.printStackTrace();}}).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone2.call(); }).start();}
}class Phone {public synchronized void sendMs() throws InterruptedException {TimeUnit.SECONDS.sleep(4);System.out.println("发短信");}public synchronized void call() {System.out.println("打电话");}public void hello() {System.out.println("hello");}
}
输出结果打电话发短信

原因:两个对象两把锁,不会出现等待的情况,发短信睡了4s,所以先执行打电话

问题五、六

如果我们把synchronized的方法加上static变成静态方法!那么顺序又是怎么样的呢?

(1)我们先来使用一个对象调用两个方法!

答案是:先发短信,后打电话

(2)如果我们使用两个对象调用两个方法!

答案是:还是先发短信,后打电话

原因是什么呢? 为什么加了static就始终前面一个对象先执行呢!为什么后面会等待呢?

原因是:对于static静态方法来说,对于整个类Class来说只有一份,对于不同的对象使用的是同一份方法,相当于这个方法是属于这个类的,如果静态static方法使用synchronized锁定,那么这个synchronized锁会锁住整个对象!不管多少个对象,对于静态的锁都只有一把锁,谁先拿到这个锁就先执行,其他的进程都需要等待!

问题七

如果我们使用一个静态同步方法、一个同步方法、一个对象调用顺序是什么

public class dome01 {public static void main(String[] args) throws InterruptedException {Phone phone1 = new Phone();
//        Phone phone2 = new Phone();new Thread(() -> {try {phone1.sendMs();} catch (InterruptedException e) {e.printStackTrace();}}).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone1.call(); }).start();}
}class Phone {public static synchronized void sendMs() throws InterruptedException {TimeUnit.SECONDS.sleep(4);System.out.println("发短信");}public synchronized void call() {System.out.println("打电话");}public void hello() {System.out.println("hello");}
}
输出结果打电话发短信

原因:因为一个锁的是Class类的模板,一个锁的是对象的调用者。所以不存在等待,直接运行。

问题八

如果我们使用一个静态同步方法、一个同步方法、两个对象调用顺序是什么?

public class dome01 {public static void main(String[] args) throws InterruptedException {Phone phone1 = new Phone();Phone phone2 = new Phone();new Thread(() -> {try {phone1.sendMs();} catch (InterruptedException e) {e.printStackTrace();}}).start();TimeUnit.SECONDS.sleep(1);new Thread(() -> { phone2.call(); }).start();}
}class Phone {public static synchronized void sendMs() throws InterruptedException {TimeUnit.SECONDS.sleep(4);System.out.println("发短信");}public synchronized void call() {System.out.println("打电话");}public void hello() {System.out.println("hello");}
}
输出结果打电话发短信

原因:两把锁锁的不是同一个东西

小解

new 出来的 this 是具体的一个对象

static Class 是唯一的一个模板

http://www.lryc.cn/news/284872.html

相关文章:

  • 集美大学“第15届蓝桥杯大赛(软件类)“校内选拔赛 D矩阵选数
  • Android System Service系统服务--1
  • 【RT-DETR有效改进】华为 | Ghostnetv1一种专为移动端设计的特征提取网络
  • 45个经典Linux面试题!赶紧收藏!
  • 将字符串中可能被视为正则表达式的特殊字符进行转义re.escape()
  • C语言:函数指针的使用
  • 「实战应用」如何用DHTMLX Gantt构建类似JIRA式的项目路线图(二)
  • Webpack5入门到原理18:Plugin 原理
  • PWM之舵机
  • Python并发与多线程:IO并发(阻塞IO、非阻塞IO、IO多路复用、异步IO)
  • React16源码: React中的IndeterminateComponent的源码实现
  • SpringBoot:详解Bean生命周期和作用域
  • 【图解数据结构】顺序表实战指南:手把手教你详细实现(超详细解析)
  • WordPress怎么禁用文章和页面古腾堡块编辑器?如何恢复经典小工具?
  • 【HarmonyOS】掌握布局组件,提升应用体验
  • 第4周:Pytorch——综合应用和实战项目 Day 28-30: 学习资源和社区参与
  • TypeScript教程(一)在vscode中的配置TypeScript环境
  • sshpass的安装与使用
  • Excel·VBA合并工作簿2
  • linux内核原理--分页,页表,内核线性地址空间,伙伴系统,内核不连续页框分配,内核态小块内存分配器
  • 【MongoDB】下载安装、指令操作
  • k8s-pvc/pv扩容记录
  • 关于Unity插件TriLib使用的一点儿心得
  • 计算机二级Python基本排序题-序号45(补充)
  • 响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例4-6 fieldset
  • html渲染优先级
  • linux 更新镜像源
  • 【征服Redis12】redis的主从复制问题
  • php函数 一
  • 监督学习 - 梯度提升回归(Gradient Boosting Regression)