synchronized到底锁住的是谁?

news2025/1/18 21:02:34

我们使用synchronized关键字是用来实现线程同步的,当多个线程同时去争抢同一个资源的时候在资源上边加一个synchronized关键字,能够使得线程排队去完成操作。
synchronized到底锁定的是什么资源?

修饰方法
    非静态方法 ,锁定的是方法的调用者。
    静态方法,锁定的是类。
修饰代码块锁定的是传入的对象

一、修饰方法

非静态方法 ,锁定的是方法的调用者

1.不加synchronized关键字,看多线程怎么执行

public class Test {
    public static void main(String[] args) {
        Data data = new Data();
        Thread t1 = new Thread(){
            @Override
            public void run(){
                data.fun1();
            }
        };
        t1.start();
        //休眠一秒钟以后再去启动2线程
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Thread t2 = new Thread(){
            @Override
            public void run(){
                data.fun2();
            }
        };
        t2.start();
    }
}
class Data{
    public void fun1(){
        //休眠3秒以后再进行输出
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("1....");
    }
    public void fun2(){
        System.out.println("2....");
    }
}

输出:首先会在1s钟以后输出 2…,然后2秒钟以后输出1…
在这里插入图片描述
在这里插入图片描述

2.加上synchronized关键字,看多线程怎么执行

public class Test {
    public static void main(String[] args) {
        Data data = new Data();
        Thread t1 = new Thread(){
            @Override
            public void run(){
                data.fun1();
            }
        };
        t1.start();
        //休眠一秒钟以后再去启动2线程
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread t2 = new Thread(){
            @Override
            public void run(){
                data.fun2();
            }
        };
        t2.start();
    }
}
class Data{
    public synchronized void fun1(){
        //休眠3秒以后再进行输出
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("1....");
    }
    public synchronized void fun2(){
        System.out.println("2....");
    }

}

输出
在这里插入图片描述
其原因是t1线程首先启动后,将资源拿到,并锁住data对象,下一秒钟t2线程启动,但是func1和func2方法的调用者都是data对象,而且data对象目前被t1锁住,所以t2线程只能等待t1线程释放资源。而t1线程一旦释放资源,t2线程会马上获得资源,进行输出。所以t1和t2线程几乎同时输出。

3.验证synchronized是否锁的是data对象

①:我们将func2方法上的synchronized关键字去除
在这里插入图片描述
在这里插入图片描述
之所以会这样输出,是因为线程1虽然先启动,并锁住了data对象,但是t2线程执行的func2方法没有synchronized修饰,那么他也就不用去争抢data对象。所以直接输出。
②:不同的对象调用方法
在这里插入图片描述
在这里插入图片描述
用不同的data对象分别去调用被synchronized修饰的func1和func2方法,然后进行执行。
在这里插入图片描述
由于t1线程锁住的是data1对象,而t2线程需要的是data2对象,所以t2线程会直接执行

静态方法,锁定的是类

1:我们让fun1()和fun2()都变成静态方法。分别让data1对象和data2对象调用!!

在这里插入图片描述
在这里插入图片描述
输出结果:
在这里插入图片描述
t1线程和t2线程同时输出,这是因为当t1线程启动起来以后,他就会锁住Data类。等t2线程启动起来以后,t2线程无法获取Data类只能等代t1线程释放资源。等到t1线程释放资源,t2线程直接获取资源启动并输出。

2.验证我们锁定的是类

我们删除fun2()当中的synchronized关键字
在这里插入图片描述
输出结果
在这里插入图片描述
在这里插入图片描述
此时我们根据输出顺序得出一个结论,两个线程没有争抢资源,因为synchronized锁住的是类,而fun2并不是类方法,所以t2线程不需要争抢资源。

二、修饰代码块 锁定的是传入的对象

1.首先我们一次性创建五个线程,并调用同一资源

在这里插入图片描述
输出的结果是:5个线程同时执行,在等待1s后同时结束,因为此时没有资源的争抢。
在这里插入图片描述

2:使用代码块锁定的传入的对象

在这里插入图片描述
在这里插入图片描述
传入this关键字,锁住的是当前对象,也就是Data对象,那么输出的顺序一定是一个个的输出。
在这里插入图片描述
多个线程争抢同一资源,那么谁先抢到谁就可以将Data对象锁住,执行function方法

3.多个线程争抢同一资源,那么谁先抢到谁就可以将Data对象锁住,执行function方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4:换个东西锁一下,证明我们锁的是传入的对象!

在这里插入图片描述
在这里插入图片描述
要想访问function方法,就必须先要获取到 1 这个对象
在这里插入图片描述
至此我们可以得出结论:修饰代码块锁定的是传入的对象。

5.有趣的知识

在这里插入图片描述
在这里插入图片描述
我们发现这里的输出和上边的输出不一致,那么这是为什么呢?
128陷阱
在这里插入图片描述
在这里插入图片描述
解析:
答案就在Integet的valueOf()方当中,如果我们的数值在-128-127之间的数值都存储在有一个catch数组当中,该数组相当于一个缓存,当我们在-128-127之间进行自动装箱的时候,我们就直接返回该值在内存当中的地址,所以在-128-127之间的数值用==进行比较是相等的。而不在这个区间的数,需要新开辟一个内存空间,所以不相等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1568988.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

效果翻倍!如何巧用邮件营销提升ROI?

我们可以通过“优化邮件内容、优化发送策略、优化数据分析、提升用户体验”来提升邮件营销ROI。 邮件营销一直被认为是一种有效的数字营销策略,可以帮助企业与潜在客户和现有客户建立联系、推广产品和服务、提高品牌认知度并促进销售。但是,为了确保邮件…

【番外篇2】统计学-方差分析

方差分析 方差分析(ANOVA)是一种用于比较三个或三个以上组之间平均值是否有显著差异的统计方法。通俗地说,就是用来确定不同组之间的平均值是否有显著差异。 让我们通过一个简单的例子来解释方差分析: 假设你是一位教育工作者&a…

day04-MQ

1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式: 同步通讯:就像打电话,需要实时响应。异步通讯:就像发邮件,不需要马上回复。 两种方式各有优劣,打电话可以立即得到响应,但是你…

【THM】Protocols and Servers 2(协议和服务器 2

介绍 协议和服务器房间涵盖了许多协议: 远程登录HTTP协议文件传输协议邮件传输协议POP3IMAP实现这些协议的服务器会受到不同类型的攻击。仅举几例,请考虑: 嗅探攻击(网络数据包捕获)中间人 ( MITM ) 攻击密码攻击(身份验证攻击)漏洞从安全的角度来看,我们始终需要思考…

易宝OA ExecuteSqlForDataSet SQL注入漏洞复现

0x01 产品简介 易宝OA系统是一种专门为企业和机构的日常办公工作提供服务的综合性软件平台,具有信息管理、 流程管理 、知识管理(档案和业务管理)、协同办公等多种功能。 0x02 漏洞概述 易宝OA ExecuteSqlForDataSet接口处存在SQL注入漏洞,未经身份认证的攻击者可以通过…

探秘采集脑电波!

原文来自微信公众号:工程师看海,与我联系:chunhou0820 看海原创视频教程:《运放秘籍》 大家好,我是工程师看海,原创文章欢迎点赞分享! 什么是脑电波?脑电波能来干嘛?怎么…

Stable Diffusion扩散模型【详解】小白也能看懂!!

文章目录 1、Diffusion的整体过程2、加噪过程2.1 加噪的具体细节2.2 加噪过程的公式推导 3、去噪过程3.1 图像概率分布 4、损失函数5、 伪代码过程 此文涉及公式推导,需要参考这篇文章: Stable Diffusion扩散模型推导公式的基础知识 1、Diffusion的整体…

【C语言】【Leetcode】【递归】22. 括号生成

文章目录 题目思路代码实现 题目 链接: https://leetcode.cn/problems/generate-parentheses/description/ 思路 我们可以通过回溯递归算法求解 如果左括号数量不大于n,我们可以放一个左括号。 如果右括号数量小于左括号的数量,我们可以放一个右括号…

sky06笔记下

1.边沿检测 检测输入信号din的上升沿&#xff0c;并输出pulse module edge_check ( clk, rstn, din, pulse ); input wire clk,rstn; input wire din; output reg pulse;wire din_dly;always (posedge clk or negedge rstn)beginif(!rstn)din_dly < 1b0;elsedin_dly < d…

Rust egui(4) 增加自己的tab页面

如下图&#xff0c;增加一个Sins也面&#xff0c;里面添加一个配置组为Sin Paraemters&#xff0c;里面包含一个nums的参数&#xff0c;范围是1-1024&#xff0c;根据nums的数量&#xff0c;在Panel中画sin函数的line。 demo见&#xff1a;https://crazyskady.github.io/index.…

b站评论词频统计绘制词云图

一、评论爬取 在笔者之前的文章中&#xff0c;已经专门介绍了b站评论的爬取&#xff08;传送门&#xff09;&#xff0c;这里只对b站评论的文本数据做展示。如下图所示&#xff1a; 二、分词、去停用词、词频统计 Python中的Jieba分词作为应用广泛的分词工具之一&#xff0c;其…

51单片机实验01-点亮LED小灯

目录 一&#xff0c;软件下载 二&#xff0c;单片机概述 1&#xff0c;单片机内部资源 1&#xff09;flash 2&#xff09;ram 3&#xff09;sfr 2&#xff0c;51单片机 3&#xff0c;单片机最小系统 三&#xff0c;点亮最右边的小灯 1&#xff0c;指出满足小灯点亮的有…

关节驱动器 CANFD 通信协议

前言 睿尔曼关节采用了问答方式进行通信&#xff0c;控制器发出指令包&#xff0c;模块返回应答包。一个CAN 总线网络中允许有多个模块&#xff0c;所以每个模块都分配有一个 ID 号。控制器发出的控制指令中包含 ID 信息&#xff0c;只有匹配上 ID 号的模块才能完整接收这条指令…

数学知识--(质数,约数)

本文用于个人算法竞赛学习&#xff0c;仅供参考 目录 一.质数的判定 二.分解质因数 三.质数筛 1.朴素筛法 2.埃氏筛法 3.线性筛法 四.约数 1.求一个数的所有约数 2.约数个数和约数之和 3.欧几里得算法&#xff08;辗转相除法&#xff09;-- 求最大公约数 一.质数的判定 …

MVCC详细总结

简介 MVCC&#xff08;Multi-Version Concurrency Control&#xff09;是一种多版本并发控制机制&#xff0c;主要用于数据库管理系统中&#xff0c;实现对数据库的并发访问。在编程语言中&#xff0c;MVCC可以实现事务内存。 MVCC的特点是读不加锁&#xff0c;读写不冲突。MVC…

Python 一步一步教你用pyglet制作“彩色方块连连看”游戏(续)

“彩色方块连连看”游戏(续) 上期讲到相同的色块连接&#xff0c;链接见&#xff1a; Python 一步一步教你用pyglet制作“彩色方块连连看”游戏-CSDN博客 第八步 续上期&#xff0c;接下来要实现相邻方块的连线&#xff1a; 首先来进一步扩展 行列的类&#xff1a; class R…

STM32 can通信部分函数注释

-----CAN1_Mode_Init CAN模式初始化函数:u8 CAN1_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode) //CAN初始化 //tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq //tbs2:时间段2的时间单元. 范围:CAN_BS2_1tq~CAN_BS2_8tq; //tbs1:时间段1的时间单元. 范…

day63 单调栈part02

503. 下一个更大元素 II 中等 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更…

vue快速入门(六)v-else和v-else-if

注释很详细&#xff0c;直接上代码 上一篇 新增内容 v-else-if用法v-else用法 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-s…

docker部署nacos,单例模式(standalone),使用内置的derby数据库,简易安装

文章目录 前言安装创建文件夹docker指令安装docker指令安装-瘦身版 制作docker-compose.yaml文件查看页面 前言 nacos作为主流的服务发现中心和配置中心&#xff0c;广泛应用于springcloud框架中&#xff0c;现在就让我们一起简易的部署一个单例模式的nacos&#xff0c;版本可…