Synchronized的三种写法

2023-11-17

文章目录

  • 前言
  • 一、synchronized是什么
  • 二、synchronized的三种写法
    • 1、同步代码块
    • 2、在实例方法上使用synchronized
    • 3、在静态方法上使用synchronized
  • 总结





前言

总结一下自己在学习Synchronized 以及它的三种写法。

一、synchronized是什么?

synchronized是由JVM实现的一种互斥同步的一种方式,被synchronized修饰过的程序块在编译前后被编译器生成了monitorenter和monitorexit两个字节码指令。

如果这个方法使用了synchronized的时候,代表它加上了锁,运行此方法的时都要检查它有没有被其他线程正在使用(或者该类的其他同步方法),有的话要等它使用完,没有的话则直接锁定调用者,然后直接运行。它包括两种用法:synchronized方法和synchronized块。



二、synchronized的三种写法




1、同步代码块

代码如下(示例):

package com.demo;

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        MyClass mc=new MyClass();
        
        Thread t1=new MyThread(mc);
        Thread t2=new MyThread(mc);
        
        t1.setName("t1");
        t2.setName("t2");
        
        t1.start();
        Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。
        t2.start();
    }

}

class MyThread extends Thread {
    private MyClass mc;
    
    public MyThread (MyClass mc) {
        this.mc = mc;
    }
    
    public void run(){
        if(Thread.currentThread().getName().equals("t1")) {
            mc.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")) {
            mc.doOther();
        }
    }
    
}

class MyClass{
    //synchronized出现再类方法上,表示锁this。
    public synchronized void doSome(){
        System.out.println("doSome 执行开始");
        try {
            Thread .sleep(1000*5);//睡眠五秒
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("doSome 执行结束");
    }
    
    public void doOther() {
        System.out.println("doOther 执行开始");
        System.out.println("doOther 执行结束");
    }
}
doOther方法执行的时候不需要等待被修饰过的doSome方法结束,因为doOther方法没有被synchronized修饰,所以它不用排队等待。 

2、在实例方法上使用synchronized

代码如下(示例):

package com.demo;

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        MyClass mc=new MyClass();
        
        Thread t1=new MyThread(mc);
        Thread t2=new MyThread(mc);
        
        t1.setName("t1");
        t2.setName("t2");
        
        t1.start();
        Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。
        t2.start();
    }

}

class MyThread extends Thread {
    private MyClass mc;
    
    public MyThread (MyClass mc) {
        this.mc = mc;
    }
    
    public void run(){
        if(Thread.currentThread().getName().equals("t1")) {
            mc.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")) {
            mc.doOther();
        }
    }
    
}

class MyClass{
    //synchronized出现再类方法上,表示锁this。
    public synchronized void doSome(){
        System.out.println("doSome 执行开始");
        try {
            Thread .sleep(1000*5);//睡眠五秒
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("doSome 执行结束");
    }
    
    public synchronized void doOther() {
        System.out.println("doOther 执行开始");
        System.out.println("doOther 执行结束");
    }
}
在两个方法前都加上synchronized修饰,doOther方法执行的时候需要等待doSome方法结束完之后才执行doSome,因为锁被doSome占了,所以要排队等待。 
我们再开启一个线程:package com.demo;

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        //开启两个线程
        MyClass mc1=new MyClass();
        MyClass mc2=new MyClass();
        
        Thread t1=new MyThread(mc1);
        Thread t2=new MyThread(mc2);
        
        t1.setName("t1");
        t2.setName("t2");
        
        t1.start();
        Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。
        t2.start();
    }

}

class MyThread extends Thread {
    private MyClass mc;
    
    public MyThread (MyClass mc) {
        this.mc = mc;
    }
    
    public void run(){
        if(Thread.currentThread().getName().equals("t1")) {
            mc.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")) {
            mc.doOther();
        }
    }
    
}

class MyClass{
    //synchronized出现再类方法上,表示锁this。
    public synchronized void doSome(){
        System.out.println("doSome 执行开始");
        try {
            Thread .sleep(1000*5);//睡眠5秒
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("doSome 执行结束");
    }
    
    public synchronized void doOther() {
        System.out.println("doOther 执行开始");
        System.out.println("doOther 执行结束");
    }
}doOther方法执行的时候不需要等待doSome方法结束,因为MyClass对象是两个,两把锁,互不干涉。 

3、在静态方法上使用synchronized

package com.demo;


public class Demo {
    public static void main(String[] args) throws InterruptedException {
        //开启两个线程
        MyClass mc1=new MyClass();
        MyClass mc2=new MyClass();
        
        Thread t1=new MyThread(mc1);
        Thread t2=new MyThread(mc2);
        
        t1.setName("t1");
        t2.setName("t2");
        
        t1.start();
        Thread.sleep(1000);//这个睡眠的作用 是为了保证t1线程先执行。
        t2.start();
    }

}

class MyThread extends Thread {
    private MyClass mc;
    
    public MyThread (MyClass mc) {
        this.mc = mc;
    }
    
    public void run(){
        if(Thread.currentThread().getName().equals("t1")) {
            mc.doSome();
        }
        if(Thread.currentThread().getName().equals("t2")) {
            mc.doOther();
        }
    }
    
}

class MyClass{
    //synchronized出现再类方法上,表示锁this。
    public synchronized static void doSome(){
        System.out.println("doSome 执行开始");
        try {
            Thread .sleep(1000*5);//睡眠5秒
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("doSome 执行结束");
    }
    
    public synchronized static void doOther() {
        System.out.println("doOther 执行开始");
        System.out.println("doOther 执行结束");
    }
}

doOther方法执行的时候不需要等待doSome方法结束,因为静态方法是类锁,不管创建了几个对象,类锁只有一把。





总结

对象锁:1个对象1把锁,100个对象有100把锁。

类锁:100个对象,全部都是这一把锁。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Synchronized的三种写法 的相关文章

随机推荐

  • IDEA:Warning: No artifacts configured FIX

    问题 办法 Warning No artifacts configured 警告 未配置项目 给idea项目添加tomcat的时候出现 解决办法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 现在还不够 16 17
  • QT连接SQLserver详细教程

    Qt 连接 SQL Sever数据库 环境 一 配置 ODBC数据源 一 在SQL Sever Manger中添加 新的用户 1 打开如下自带的 MSS Management Studio 2 登录时选择 Windows 身份验证 3 去往
  • 在python中使用python-docx实现word文档自动化

    五一马上就要结束了 趁着今天休息的一天 给大家说说在python对办公文档处理 文章中说要详细的介绍python中几个对文档处理的库 今天就介绍一下word文档处理的python docx库 好了废话不多说开始吧 哈哈哈哈哈哈哈啊哈哈 py
  • 学习MongoDB 三: MongoDB无法启动的解决方法

    一简介 我们之前介绍了MongoDB入门 安装与配置 我们今天在打开MongDB时 我们先运行cmd exe进入dos命令界面 然后进入cd D mongodb bin目录下 启动服务或者mongo命令都报了错误 二 解决 1 net st
  • vue实现三级联动

    div div
  • 图片在盒子内等比展示不变形

    通过这个属性 object fit cover 使用场景如下 fatherBox 父盒子要有宽高 width 240px height 240px sonBox 子盒子 width 100 height 100 object fit cov
  • 7种Git错误以及解决方法

    使用Git的时候如果出现报错 要会解决Git错误 以下整理了七种Git错误以及解决的方法 1 当出现fatal not a git repository or any of the parent directories git时 说明不是一
  • vector find() 用法

    int main vector
  • STM32的PA0输出高电平的具体库函数代码操作

    在STM32中 可以使用库函数控制PA0输出高电平 具体的代码如下 初始化GPIOA的引脚模式 设置PA0为输出模式 GPIO InitTypeDef GPIO InitStruct HAL RCC GPIOA CLK ENABLE GPI
  • Score SDE 三种随机微分方程代码解读

    定义SDE类 定义了7个子函数 T End time of the SDE sde marginal prob Parameters to determine the marginal distribution of the SDE p t
  • 计算机二级-简单应用题

    题目要求 编写代码 以实现如下功能 键盘输入小明学习的课程名称及考分等信息 信息间采用空格分隔 每个课程一行 空行回车结束录入 示例格式如下 数学 90 语文 95 英语 86 物理 84 生物 87 屏幕输出得分最高的课程及成绩 得分最低
  • 去除指定css属性

    使得指定css样式失效 layui btn background image initial important 优先使用 layui btn background image initial important padding 0 10p
  • 像程序员一样思考_如何像程序员一样思考-解决问题的经验教训

    像程序员一样思考 by Richard Reis 理查德 里斯 Richard Reis 如何像程序员一样思考 解决问题的经验教训 How to think like a programmer lessons in problem solv
  • Vue-router2.0基础,秒会。

    如果不是模块式开发 请先引入 1 0基础 div h1 Hello App h1 p p div
  • Docker打开远程API服务

    一 开发环境 1 系统环境 2 docker版本 二 步骤 1 查看docker配置文件路径 2 编辑配置文件 3 重启docker 三 测试 1 查看docker客户端服务端版本 docker H localhost 2375 versi
  • C++ 在一个程序中调用exe

    生成exe的代码 include
  • StarRocks 运维工具 StarGo

    优质资源分享 学习路线指引 点击解锁 知识定位 人群定位 Python实战微信订餐小程序 进阶级 本课程是python flask 微信小程序的完美结合 从项目搭建到腾讯云部署上线 打造一个全栈订餐系统 Python量化交易实战 入门级 手
  • Spring Boot Admin 监控告警

    Spring Boot Admin 监控告警 要进行监控 需要两个Project 一个是Admin Server端 负责监控Spring boot的项目 另一个是Admin Client端 是被监控的Spring boot服务 当然也可以一
  • Android优化

    一 布局优化 布局优化就是删除布局中无用的控件和层级 可以用Hierarchy Viewer工具来检测 其次有选择地使用性能较低的ViewGroup include标签 include标签只支持以android layout开头的属性 比如
  • Synchronized的三种写法

    文章目录 前言 一 synchronized是什么 二 synchronized的三种写法 1 同步代码块 2 在实例方法上使用synchronized 3 在静态方法上使用synchronized 总结 前言 总结一下自己在学习Synch