synchronized到底锁住的是谁?

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

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

一、修饰方法

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

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

public class Test {public static void main(String[] args) {Data data = new Data();Thread t1 = new Thread(){@Overridepublic void run(){data.fun1();}};t1.start();//休眠一秒钟以后再去启动2线程try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}Thread t2 = new Thread(){@Overridepublic 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(){@Overridepublic void run(){data.fun1();}};t1.start();//休眠一秒钟以后再去启动2线程try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}Thread t2 = new Thread(){@Overridepublic 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.mzph.cn/news/794162.shtml

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

相关文章

《UE5_C++多人TPS完整教程》学习笔记30 ——《P31 摄像机和弹簧臂(Camera And Spring Arm)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P31 摄像机和弹簧臂(Camera And Spring Arm)》 的学习笔记,该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版,UP主(…

使用git 和 github协作开发

文章目录 github浏览器汉化插件github新建仓库git安装以及ssh配置团队创建及基本命令的使用创建团队基本命令 分支管理快速切换远程仓库地址 如何使用git && github进行协作开发,包括git常见基础命令 github浏览器汉化插件 在刚开始使用github的时候&#…

ubuntu安装docker,并搭建vulfocus靶场

ubuntu安装docker,并搭建vulfocus靶场 docker是一个容器管理的软件,容器背后其实就是一个进程;类似于一个集装箱。 docker的官方下载地址:Install Docker Engine on Ubuntu | Docker Documentation(可以根据自己需要的…

【文献分享】机器学习 + 分子动力学 + 第一性原理 + 热力学性质 + 微观结构

分享一篇关于机器学习 分子动力学 第一性原理 热学性质(密度、比热容、导热率和粘度) 微观结构的文章。 感谢论文的原作者! 关键词: 1. Deep potential 2. Machine learning 3. Molecular dynamics 4. Microscopic structu…

Linux| Awk 中“next”命令奇用

简介 本文[1]介绍了在Linux中使用Awk的next命令来跳过剩余的模式和表达式,读取下一行输入的方法。 next命令 在 Awk 系列教程中,本文要讲解如何使用 next 命令。这个命令能让 Awk 跳过所有你已经设置的其他模式和表达式,直接读取下一行数据。…

【无标题】【Android】Android中Intent的用法总结

2.显示地图: Java代码 Uri uri Uri.parse(“geo:38.899533,-77.036476”); Intent it new Intent(Intent.Action_VIEW,uri); startActivity(it); 3.从google搜索内容 Java代码 Intent intent new Intent(); intent.setAction(Intent.ACTION_WEB_SEARCH); intent.pu…

【C++进阶】【STL】set和map的讲解及模拟实现

🪐🪐🪐欢迎来到程序员餐厅💫💫💫 主厨:邪王真眼 主厨的主页:Chef‘s blog 所属专栏:c大冒险 总有光环在陨落,总有新星在闪烁 一、 关联式容器 在初阶阶…

github中git clone需要username和password问题

username:一般指你的昵称 password:一般指Creating a fine-grained personal access token 这个的获取办法如下(注意,在11步的时候,记得打开你仓库对应的一些access 权限): Note: Fine-graine…

动态规划刷题(算法竞赛、蓝桥杯)--线段(线性DP)

1、题目链接&#xff1a;P3842 [TJOI2007] 线段 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include <bits/stdc.h> using namespace std; const int N20010; int a[N][2],f[N][2]; //a[i][0]表示l[i],a[i][1]表示r[i] int dis(int a,int b){return abs(a-b); } int…

Java中的网络编程(一)

一、网络编程概述 什么是计算机网络把不同区域的计算机&#xff08;广义&#xff09;通过通信设备和线路连接&#xff0c;可以实现数据的传输和共享的系统。实现不同计算机之间的练习&#xff0c;必须有介质连接。网络编程是干什么的聊天-->聊天软件 QQjava语言是支持网络间…

从人机界面设计黄金三法则视角看 ChatGPT 的界面设计的“好”与“坏”

热门文章推荐&#xff1a; &#xff08;1&#xff09;《为什么很多人工作 3 年 却只有 1 年经验&#xff1f;》&#xff08;2&#xff09;《一文掌握大模型提示词技巧&#xff1a;从战略到战术巧》&#xff08;3&#xff09;《AI 时代&#xff0c;程序员的出路在何方&#xff1…

数组方法汇总

数组和链表类似&#xff0c;都是用双指针&#xff0c;但数组不需要额外的指针&#xff0c;可以使用索引来当作指针。&#xff08;链表的时候要注意&#xff0c;什么时候是移动的指针&#xff0c;什么时候是改变的节点&#xff09;删除有序数组中的重复项 注意&#xff0c;本题中…

36.基于CAS实现的java类

JUC, java.util.concurrent并发工具包下。 1.原子整数 AtomicInteger AtomicLong AtomicBoolean 底层用的CAS来实现。 AtomicInteger类的incrementAndGet方法&#xff0c;addAndGet方法 public static void main(String[] args) {AtomicInteger atomicInteger new Atom…

Coursera自然语言处理专项课程04:Natural Language Processing with Attention Models笔记 Week01

Natural Language Processing with Attention Models Course Certificate 本文是学习这门课 Natural Language Processing with Attention Models的学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。 文章目录 Natural Language Processing with Attention ModelsWeek 01…

c# wpf style 简单试验

1.概要 wpf style 用来控制控件的样式 2.代码 <Window x:Class"WpfApp2.Window5"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.…

MCAL SPI配置

用的是Qspi0 SpiDriver 要配置 4个选项 Spichannel SpiExternalDevice SpiJob SpiSequence Mcu 模块配置 dma配置

开发环境->生产环境

1、数据迁移 不涉及docker # 以数据库用户导出数据 mysqldump -h 192.168.1.168 -P 3307 -u abragent -pabragebb17 abragent > abragent.sql# 以root用户导出数据 mysqldump -h 192.168.1.168 -P 3307 -u root -p8d3Ba1b abragent > abragent.sql 涉及docker …

递归算法练习

递归算法是所有算法中较难的一种&#xff0c;依靠他代码的简洁和清晰地逻辑很受人们喜欢&#xff0c;但是新手入门递归还是会被他不同寻常的思路吓到&#xff0c;其实面对递归问题我们只需要看清题目&#xff0c;分析出要求&#xff0c;有清晰的解题思路&#xff0c;只要仔细分…

软考--软件设计师(软件工程总结2)

目录 1.测试方法 2.软件项目管理 3.软件容错技术 4.软件复杂性度量 5.结构化分析方法&#xff08;一种面向数据流的开发方法&#xff09; 6.数据流图 1.测试方法 软件测试&#xff1a;静态测试&#xff08;被测程序采用人工检测&#xff0c;计算机辅助静态分析的手段&…

虚拟机打不开

问题 另一个程序已锁定文件的一部分&#xff0c;进程无法访问 打不开磁盘“G:\centeros\hadoop104kl\hadoop100-cl2.vmdk”或它所依赖的某个快照磁盘。 模块“Disk”启动失败。 未能启动虚拟机。 原因 前一次非正常关闭虚拟机导致.lck 文件是VMWare软件的一种磁盘锁文件&…