synchronized到底锁住的是谁?

我们使用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之间的数值用==进行比较是相等的。而不在这个区间的数,需要新开辟一个内存空间,所以不相等。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 1379.找出克隆二叉树中的相同节点:二叉树遍历

【LetMeFly】1379.找出克隆二叉树中的相同节点:二叉树遍历 力扣题目链接:https://leetcode.cn/problems/find-a-corresponding-node-of-a-binary-tree-in-a-clone-of-that-tree/ 给你两棵二叉树,原始树 original 和克隆树 cloned&#xff0…

SpringMvc工作流程

用户通过浏览器发送请求到前端控制器DispatcherServlet。前端控制器直接将请求转给处理器映射器HandlerMapping。处理器映射器HandlerMapping会根据请求,找到负责处理该请求的处理器,并将其封装为处理器执行链HandlerExecutionChina后返回给前端控制器Di…

Linux初学(十四)LampLnmp

一、简介 LAMP和LNMP是两种常见的web服务器组合。具体如下: LAMP:LAMP代表的是Linux(操作系统) Apache(HTTP服务器) MySQL(数据库) PHP(编程语言)。这个组合被…

好用的Android Studio插件管理器

1.使用阿里云的通义灵码方便快速开发 1.1下载插件File->plugin->marketplace 搜索 Tongyilingma然后安装重启登录阿里云,确认 1.2 使用方法 输入信息描述 比如 //写一段冒泡排序然后换行,输入public/private/protected方法会自动生成联想代码…

Ubuntu18.04+2070s+TF2.x环境,单卡训练PointNet++实战

Ubuntu18.042070sTF2.x环境,单卡训练PointNet实战 1. 编译tf_ops文件夹下的三个动态库2. 修改Python版本、TF版本不一致带来的差异3. 下载训练数据4. 模型训练 1. 编译tf_ops文件夹下的三个动态库 该文件夹下定义了一些pointnet模型中需要使用的cuda核函数&#xf…

elsint报错Delete `␍`eslintprettier/prettier

一,原因 这篇博客写得很清楚:解决VSCode Delete ␍eslint(prettier/prettier)错误_vscode 删除cr-CSDN博客 还有这篇文章,解决办法很详细:滑动验证页面 二,解决办法 根目录下新建.prettierrc.js文件 module.exports…

Linux-程序地址空间

目录 1. 程序地址空间分布 2. 两个问题 3. 虚拟地址和物理地址 4. 页表 5. 解决问题 6. 为什么要有地址空间 1. 程序地址空间分布 测试一下&#xff1a; #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h>int ga…

C#仿OutLook的特色窗体设计

目录 1. 资源图片准备 2. 设计流程&#xff1a; &#xff08;1&#xff09;用MenuStrip控件设计菜单栏 &#xff08;2&#xff09;用ToolStrip控件设计工具栏 &#xff08;3&#xff09;用StatusStrip控件设计状态栏 &#xff08;4&#xff09;ImageList组件装载树节点图…

小米手机刷入Root权限

小米手机刷入Root权限 解Bi锁下载刷机包刷入Root准备工作开始刷入 验证root 解Bi锁 下载地址&#xff1a;小米BI官方解锁工具需要先申请&#xff0c;申请通过才能解锁注意&#xff1a;解BI锁会清除所有数据。 下载刷机包 根据自己的手机型号和版本到小米官网下载和自己手机版…

android framework 学习笔记(1)

学习资料&#xff1a;《Android Framework 开发揭秘》_哔哩哔哩_bilibili 什么是android framework 看图说话&#xff0c;android框架从上至下分为&#xff1a; 应用层(Application)&#xff0c;Java framework(Application Framework),Native framework. 包括Libraries 和 A…

基于JSP杏种质资源管理系统

摘要 社会的进步导致人们对于学习的追求永不止境&#xff0c;那么追求农业信息化的方式也从单一的田地教程变成了多样化的学习方式。多样化的学习方式不仅仅是需要人们智慧的依靠&#xff0c;还需要能够通过软件的加持进行信息化的价值体现。软件和系统的产生&#xff0c;从表…

【mT5模型】mT5: A Massively Multilingual Pre-trained Text-to-Text Transformer

【mT5模型】mT5: A Massively Multilingual Pre-trained Text-to-Text Transformer 论文信息 阅读评价 Abstract Introduction Background on T5 and C4 mC4 and mT5 mC4 mT5 Comparison to related models Experiments Zero-shot generation Illegal predictions Pre…

【Pyhton中requests库、re库、文件读写的了解】

1、requests库&#xff1a;第三方库&#xff0c;主要用于Python发送HTTP请求 response1 requests.get(https://www.qq.com/) # 发送get请求 # requestdata {User-Agen: KWHJJKLK, Accept: text/html, Cookie: sjdshkwje213} # 请求数据 # response2 requests.post(https:…

C++(13): 智能指针shared_ptr

1. 概述 shared_ptr智能指针&#xff0c;本质是“离开作用域会自动调整(减小)引用计数&#xff0c;如果引用计数为0&#xff0c;则会调用析构函数”。这样一来&#xff0c;就进化成类似于int、float等的一种会被自动释放的类型。 2. 初始化智能指针 初始化一个智能指针的方式比…

基于springboot实现房屋租赁管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现房屋租赁系统演示 摘要 房屋是人类生活栖息的重要场所&#xff0c;随着城市中的流动人口的增多&#xff0c;人们对房屋租赁需求越来越高&#xff0c;为满足用户查询房屋、预约看房、房屋租赁的需求&#xff0c;特开发了本基于Spring Boot的房屋租赁系统。 …

python怎么存储数据

在Python开发中&#xff0c;数据存储、读取是必不可少的环节&#xff0c;而且可以采用的存储方式也很多&#xff0c;常用的方法有json文件、csv文件、MySQL数据库、Redis数据库以及Mongdb数据库等。 1. json文件存储数据 json是一种轻量级的数据交换格式&#xff0c;采用完全…

FreeRTOS第四天

1.总结二进制信号量和计数型信号量的区别&#xff0c;以及他们的使用场景。 进制信号量&#xff1a;信号量的数值只有0和1。(用于共享资源的访问&#xff09; 计数型信号量: 计数型信号量的值一般是大于或者等于2 (生产者和消费者模型) 2.使用技术型信号量完成生产者和消费者模…

掌握 Go 语言的 defer 关键字

关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等&#xff0c;您的关注将是我的更新动力&#xff01; 在 Go 语言编程中&#xff0c;文件的输入/输出是一个常见的操作。我们知道&#xff0c;每次打开文件后&#xff0c;都需要在操作…

在Linux系统上搭建Android、Linux和Chrome性能监控和Trace分析的系统

perfetto是知名的Android系统性能分析平台。我们还可以用它去分析Linux系统和Chrome&#xff08;需要装扩展&#xff09;。本文我们只介绍如何安装的验证。 部署 我们使用Docker部署perfetto ui系统。 FROM ubuntu:20.04 WORKDIR /perfetto-ui RUN apt-get update -y RUN ap…

蓝桥集训之阶乘分解

蓝桥集训之阶乘分解 核心思想&#xff1a;线性筛质数 筛出每一个质数后 只要将所有质数的1 2 3 … 次方个数都加上即可 #include <iostream>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int N 1e610;int …