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

synchronized锁的八种情况

概述

记录和理解synchronized锁的八种情况。

定义

一个手机类,三个方法。发消息,发邮件,说你好。前面两者都加了synchronized关键字。

@Data
public class Phone {public synchronized void sendMsg(){System.out.println("send msg");}public synchronized void sendEmail(){System.out.println("send email");}public void sayHello(){System.out.println("hello");}}

第一种情况-普通情况-先发消息,后发邮件

中间加了sleep,保证先发送消息,后发送邮件。

    public static void test1() throws Exception {Phone phone = new Phone();new Thread(() -> {phone.sendMsg();}, "a").start();Thread.sleep(1000);new Thread(() -> {phone.sendEmail();}, "b").start();}

第二种情况-发送消息时sleep 4s-先发消息,后发邮件

更改手机的方法,让其在发送消息时先睡4s

@Data
public class Phone {public synchronized void sendMsg() throws InterruptedException {Thread.sleep(4000);System.out.println("send msg");}public synchronized void sendEmail(){System.out.println("send email");}public void sayHello(){System.out.println("hello");}}

测试方法

    public static void test2() throws Exception {Phone phone = new Phone();new Thread(() -> {try {phone.sendMsg();} catch (InterruptedException e) {throw new RuntimeException(e);}}, "a").start();Thread.sleep(1000);new Thread(() -> {phone.sendEmail();}, "b").start();}

测试结果
在这里插入图片描述
从结果来看,先发消息,后发邮件。虽然说发消息时睡了4s,但还是先发消息。
这是因为加了synchronized锁,锁的是当前的phone对象,由于测试代码中,是先执行sendMsg方法的,所以该方法先拿到了锁资源。所以sendEmail方法要等sendMsg方法释放锁资源后才能获取锁,再执行sendEmail方法。

第三种情况-先说你好,再发消息

phone的方法不变,修改测试方法。

    public static void test3() throws Exception {Phone phone = new Phone();new Thread(() -> {try {phone.sendMsg();} catch (InterruptedException e) {throw new RuntimeException(e);}}, "a").start();Thread.sleep(1000);new Thread(() -> {phone.sayHello();}, "b").start();}

测试结果
在这里插入图片描述
测试方法中,虽然先调用sendMsg方法,但是其本身睡4s,而且sayHello方法是没有加sychronized锁的,所以当主线程睡了1s后就直接执行sayHello方法了。

第四种情况-两部手机-先发邮件,再发消息

phone类定义不变
测试方法,实例一个新手机,两个手机执行不同方法。

    public static void test4() throws Exception {Phone phone1 = new Phone();Phone phone2 = new Phone();new Thread(() -> {try {phone1.sendMsg();} catch (InterruptedException e) {throw new RuntimeException(e);}}, "a").start();Thread.sleep(1000);new Thread(() -> {phone2.sendEmail();}, "b").start();}

测试结果
在这里插入图片描述
这是因为synchronized锁的是实例对象,phone1和phone2是两个实例,所以不会影响。

第五种情况-两个静态同步方法,1个手机,先发消息还是发邮件-先发消息,再发邮件

修改phone类

@Data
public class Phone {public static synchronized void sendMsg() throws InterruptedException {Thread.sleep(4000);System.out.println("send msg");}public static synchronized void sendEmail(){System.out.println("send email");}public void sayHello(){System.out.println("hello");}}

测试方法

public static void test5() throws Exception {Phone phone= new Phone();new Thread(() -> {try {phone.sendMsg();} catch (InterruptedException e) {throw new RuntimeException(e);}}, "a").start();Thread.sleep(1000);new Thread(() -> {phone.sendEmail();}, "b").start();}

测试结果
在这里插入图片描述
这是因为两个方法加了static关键字,那么synchronized锁的是Phone这个类。所以sendMsg和sendEmail相当于串行执行了。

第六种情况-两个静态同步方法,2个手机,先发消息还是发邮件-先发消息,再发邮件

测试方法

public static void test6() throws Exception {Phone phone1= new Phone();Phone phone2= new Phone();new Thread(() -> {try {phone1.sendMsg();} catch (InterruptedException e) {throw new RuntimeException(e);}}, "a").start();Thread.sleep(1000);new Thread(() -> {phone2.sendEmail();}, "b").start();}

测试结果
在这里插入图片描述
其实加了static,synchronzed锁的是这个Phone类,其锁的范围比锁实例时更大。

第七种情况-一个静态方法,一个普通方法,1个手机-先发邮件,再发消息

修改phone类,sendEmail变成普通方法

@Data
public class Phone {public static synchronized void sendMsg() throws InterruptedException {Thread.sleep(4000);System.out.println("send msg");}public synchronized void sendEmail(){System.out.println("send email");}public void sayHello(){System.out.println("hello");}}

测试代码

    public static void test7() throws Exception {Phone phone= new Phone();new Thread(() -> {try {phone.sendMsg();} catch (InterruptedException e) {throw new RuntimeException(e);}}, "a").start();Thread.sleep(1000);new Thread(() -> {phone.sendEmail();}, "b").start();}

测试结果
在这里插入图片描述
第七第八种情况都说明了锁的范围和对象不同。
static+synchronized 锁的是Class对象。
sychronized 锁的是this对象。

第八种情况-一个静态方法,一个普通方法,2个手机-先发邮件,再发消息

测试代码

public static void test8() throws Exception {Phone phone1= new Phone();Phone phone2= new Phone();new Thread(() -> {try {phone1.sendMsg();} catch (InterruptedException e) {throw new RuntimeException(e);}}, "a").start();Thread.sleep(1000);new Thread(() -> {phone2.sendEmail();}, "b").start();}

测试结果
在这里插入图片描述


http://www.mrgr.cn/news/68268.html

相关文章:

  • 「C/C++」C/C++ 指针篇 之 指针运算
  • 【ChatGPT】如何通过逐步提示提高ChatGPT的细节描写
  • el-date-picker 设置开始时间和结束时间
  • 解锁炎症和肿瘤免疫治疗新靶点:TREM1&TREM2
  • oracle-函数-grouping sets(x1,x2,x3...)的妙用
  • 【React】JSX规则
  • uniapp的基本使用(easycom规范和条件编译)和uview组件的安装和使用
  • 数据挖掘实战-基于SARIMA时间序列模型预测Netflix股票未来趋势
  • 虚拟化数据恢复—XenServer虚拟机中SQL Server数据库数据恢复案例
  • 常用滤波算法(十一)-卡尔曼滤波
  • 【数据结构】哈希/散列表
  • 制造业数据架构设计顶层规划方案
  • fs 中的 rmSync 中的参数配置
  • JDBC入门
  • 前端 Canvas 绘画 总结
  • Hive简介 | 体系结构
  • 【AIGC探索】AI实现PPT生产全流程
  • unplugin-auto-import 库作用
  • Excel和微软小冰的结合应用
  • (62)使用RLS自适应滤波器进行系统辨识的MATLAB仿真
  • 220亿巨资注入,农业强国梦想加速启航!
  • 小张求职记六
  • 【云原生开发】K8S集群管理后端开发设计与实现
  • 员工培训对六西格玛管理的落地有哪些帮助?
  • 每日八股——java中的注解原理是什么?
  • C++网络编程之IO多路复用(二)