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

java并发:synchronized锁详解

背景:

        在java多线程当中,我们总有遇到过多个线程操作一个共享数据时,而这个最后的代码执行结果并没有按照我们的预期一样得到正确的结果。此时我们就需要让代码执行在操作共享变量时,要等一个线程操作完毕时,另一个线程才能去操作这个共享变量。synchronized锁就能达到这样的目的。在线程A操作某个共享变量时,其他线程想要操作这个对像的话只能先处于等待状态,只有线程A操作完毕后其他线程才能操作这个变量。synchronized还有一个作用,就是将让其他线程看到这个线程内对像的变化,获取到对像的最新的值。

sychronized锁的使用方式

        利用synchronized实现同步的基础:Java中的每一个对象都可以作为锁。具体表现 为以下3种形式。

  • 对于普通同步方法,锁是当前实例对象。
  • 对于静态同步方法,锁是当前类的Class对象。
  • 对于同步方法块,锁是Synchonized括号里配置的对象。

下面我对于这三种方式进行详细的说明,但再此之前要介绍多线程操作共享变量的内存图:

 多线程处理共享数据是从主内存中将数据拷贝一份到自己的工作内存当中,再工作内存当中对其进行操作,然后再写回到主内存当中。

对于普通同步方法,锁是当前实例对象。

        当sychronized修饰普通方法时,这个方法已经变为了同步方法,并对这个对象加了锁,此时想要操作这个对像的同步方法要先获得这个对像的锁,所以说这个加锁并不是其他线程都无法访问这个对象了,而是无法访问这个对像内被sychronized修饰变为同步方法的方法了,其他方法并不受影响。

public class ThreadTest {public synchronized  void m1() {    //同步方法System.out.println("m1方法开始");try {Thread.sleep(1000);} catch (Exception e) {}System.out.println("m1方法结束");}public synchronized void m2() {   //同步方法System.out.println("m2方法开始");try {Thread.sleep(1000);} catch (Exception e) {}System.out.println("m2方法结束");}public static void main(String[] args) {ThreadTest threadTest = new ThreadTest();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {threadTest.m1();}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {threadTest.m2();}});t1.start();t2.start();}
}

此时m1和m2方法都是同步方法,我们创建一个ThreadTest对像,然后用两个线程分别调用同一个对像的m1和m2方法,根据前面两个所讲,可以预测由于线程1执行方法m1时就拿到了这个对像锁,则其他线程无法执行这个对像的其他同步方法。执行结果不出我们所料:

确实是线程1先执行m1,等其执行完毕后线程2再执行的m2方法。当我们将m2变为普通方法(不被关键字synchronized修饰),然后执行:

这时候就没有等待线程1执行同步方法m1完毕后线程2再调用m2方法。因为此时执行普通方法m2不需要这个对像的锁,也就不用等待线程A执行完释放锁了。

对于静态同步方法,锁是当前类的Class对象。 

        当synchronized修饰的是静态方法时,此时加锁的并不是这个类的实例对象了,而是这个类的Class对象。此时和前面那种形式有一些不同了。但一个线程调用这个静态同步方法时会获取到这个Class对像的锁,其他线程就不能再执行这个类的其他静态同步方法。但可以调用其他普通的静态方法和普通方法。同时也可以调用它的普通同步方法,因为调用这两者方法需要的锁并不一样,一个是类锁,一个是对像锁,所以他们并不互斥。下面代码结果展示一下:

public class ThreadTest {public synchronized  void m1() {System.out.println("m1方法开始");try {Thread.sleep(1000);} catch (Exception e) {}System.out.println("m1方法结束");}public synchronized static void m2() {System.out.println("m2方法开始");try {Thread.sleep(1000);} catch (Exception e) {}System.out.println("m2方法结束");}public synchronized static void m3() {System.out.println("m3方法开始");try {Thread.sleep(1000);} catch (Exception e) {}System.out.println("m3方法结束");}public static void main(String[] args) {ThreadTest threadTest = new ThreadTest();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {threadTest.m1();}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {ThreadTest.m2();}});Thread t3 = new Thread(new Runnable() {@Overridepublic void run() {ThreadTest.m3();}});t1.start();t2.start();t3.start();}
}

我定义了三个方法都用synchronized修饰了,m1是普通同步方法,而m2、m3是静态同步方法,并用三个线程分别调用这三个方法。按照前面原理解释,m1方法和m2、m3这两个方法不互斥,m2和m3这两个方法互斥。

由结果看出,m1和m2方法可以看出不互斥,同时执行,并没有等待,而m3方法是再m2方法完全执行完毕后再执行的。可以说明m2执行时获取了Class对象的锁,而静态同步方法m3想要执行的话,就得等待锁的释放才能执行,最终产生了上面的执行结果。 

对于同步方法块,锁是Synchonized括号里配置的对象。

        锁住同步方法块,锁是synchonized括号里面那个引用类型对像(注意:能作为锁的只能是引用类型,不能是基本数据类型)。这样子实现的功能是:因为线程的切换是随机的,但我们要保证一段代码一定要全部执行,不想被执行到一办事就被切换到其他线程,无法保证线程安全。此时就需要synchonized来锁住这段代码了。还有就是想要执行这个代码块就得先获取到相对应的对象锁。也就是说当两个线程执行两个拿同一个对象作为锁的代码块,则两者不能同时执行,必须等一个代码块执行完毕,释放锁后,另一个线程才能获取这个对像锁然后执行。

public class ThreadTest {public static Object o = new Object();public   void m1() {synchronized(o) {System.out.println("m1方法开始");try {Thread.sleep(1000);} catch (Exception e) {}System.out.println("m1方法结束");}}public   void m2() {synchronized(o){System.out.println("m2方法开始");try {Thread.sleep(1000);} catch (Exception e) {}System.out.println("m2方法结束");}}public static void main(String[] args) {ThreadTest threadTest = new ThreadTest();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {threadTest.m1();}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {threadTest.m2();}});t1.start();t2.start();}
}

代码中两个线程各执行一个代码块,两个代码块用的是同一个对象锁,则他们不能同时执行是互斥的。

由输出结果可以看出,线程2中的代码块是等线程1执行完其内的代码块并释放锁后再执行的。 

相关文章:

java并发:synchronized锁详解

背景: 在java多线程当中,我们总有遇到过多个线程操作一个共享数据时,而这个最后的代码执行结果并没有按照我们的预期一样得到正确的结果。此时我们就需要让代码执行在操作共享变量时,要等一个线程操作完毕时,另一个线程…...

Unity 之NavMeshAgent 组件(导航和路径寻找的组件)

文章目录 **作用**:**属性和方法**:**用途**:**注意事项**: NavMeshAgent 是Unity引擎中用于导航和路径寻找的组件。它可以使游戏对象在场景中自动找到可行走的路径,并在避免障碍物的情况下移动到目标位置。 以下是关于…...

装箱和拆箱

1. 概念 装箱 将值类型转换成等价的引用类型 装箱的步骤 拆箱 将一个已装箱的引用类型转换为值类型,拆箱操作需要声明拆箱后转换的类型 拆箱的步骤 1)获取已装箱的对象的地址 2)将值从堆上的对象中复制到堆栈上的值变量中 2. 总结 装箱和拆箱…...

等保测评--安全通信网络--测评方法

安全子类--安全架构 a)应保证网络设备的业务处理能力满足业务高峰期需要; 一、测评对象 路由器、交换机、无线接入设备和防火墙等提供网络通信功能的设备或相关组件 二、测评实施 1) 应核查业务高峰时期一段时间内主要网络设备(一般包括核心交换机、汇聚交换机、边界路…...

统计学补充概念11-tsne

概念 t-SNE(t-distributed Stochastic Neighbor Embedding)是一种非线性降维技术,用于可视化高维数据在低维空间中的分布。与主成分分析(PCA)等线性降维方法不同,t-SNE专注于保留数据点之间的局部相似性关…...

Linux_11_系统启动和内核管理

目录 1 C entOS 6 的启动管理1.1 Linux 组成1.2 内核设计流派1.3 CentOS 6启动流程1.3.1 CentOs 6 启动流程1.3.1 硬件启动POST1.3.2 bootloader 启动/引导加载器1.3.2.1 grub 功能和组成1.3.2.2 CentOS 6 grub 安装1.3.2.3 grub legacy 管理 1.3.3 加载 kernel1.3.4 init 初始…...

【从零学习python 】65. Python正则表达式修饰符及其应用详解

文章目录 正则表达式修饰符进阶案例 正则表达式修饰符 修饰符描述re.I使匹配对大小写不敏感re.M多行匹配,影响 ^ 和 $re.S使 . 匹配包括换行在内的所有字符 示例代码如下: import reprint(re.search(rL, hello)) # None# 不区分大小写,可…...

QA2

1. import shutil 是什么意思? 在 Python 中,import shutil 是导入标准库 shutil 的语句。shutil 提供了一些用于复制文件和文件夹、移动文件和文件夹、以及执行其他文件操作的函数。 通过导入 shutil,你可以使用其中的函数来处理文件和文件…...

centos7卸载docker

要在CentOS 7上干净地卸载Docker,可以执行以下步骤: 停止Docker服务: sudo systemctl stop docker移除所有Docker容器和镜像。这将删除所有相关数据,包括容器、镜像以及存储卷等。请注意,这将不可逆转地删除数据。 …...

【计算机视觉】递归神经网络在图像超分的应用Deep Recursive Residual Network for Image Super Resolution

DRCN: Deeply-Recursive Convolutional Network for Image Super-Resolution 总结 这篇文章是第一次将之前已有的递归神经网络(Recursive Neural Network)结构应用在图像超分辨率上。为了增加网络的感受野,提高网络性能,引入了深度递归神经网络&#x…...

Centos 7 安装系列(8):openGauss 3.0.0

安装依赖包: yum -y install libaio-devel flex bison ncurses-devel glibc-devel patch redhat-lsb-core readline-devel openssl-devel sqlite-devel libnsl 安装插件: yum install -y bzip2 net-tools为什么要安装这两个? 安装bzip2 是…...

NOIP真题讲解 传球游戏 接水问题

传球游戏 说明 上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起做传球游戏。 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,…...

《论文阅读18》 SSD: Single Shot MultiBox Detector

一、论文 研究领域: 2D目标检测论文:SSD: Single Shot MultiBox Detector ECCV 2016 数据集 论文链接论文github 二、论文概要 SSD网络是作者Wei Liu在ECCV 2016上发表的论文。对于输入尺寸300x300的网络 使用Nvidia Titan X在VOC 2007测试集上达到74…...

NOIP2016普及组第四题 魔法阵

魔法阵 题目描述 六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量。 大魔法师有m个魔法物品,编号分别为1,2,…,m。每个物品具有一个魔法值,我们用Xi表示编号为i的物品的魔法值。每个魔法值Xi是不超过n的正整数&…...

uniapp-滑块验证组件wo-slider

wo-slider是一款支持高度自定义的滑块验证组件,采用uniapp-vue2编写 采用touchstart、touchmove、touchend事件实现的滑块组件,支持H5、微信小程序(其他小程序未试过,可自行尝试) 可到插件市场下载尝试: https://ext.…...

NPM 管理组织成员

目录 1、向组织添加成员 1.1 邀请成员加入您的组织 1.2 撤销组织邀请 2、接收或拒接组织邀请 2.1 接收组织邀请 2.2 拒绝组织邀请 3、组织角色和权限 4、管理组织权限 5、从组织中删除成员 1、向组织添加成员 作为组织所有者,您可以将其他npm用户添加到…...

设计模式(3)抽象工厂模式

一、概述: 1、提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。 2、结构图: 3、举例代码: (1) 实体: public interface IUser {public void insert(User user);public…...

【C++】早绑定、析构与多态 | 一道关于多态的选择题记录

今天在和群友聊天的时候看到了一道很坑的题目&#xff0c;分享给大家 1.看题&#xff01; 先来看看题目 struct Dad { public:Dad(){ echo();}~Dad(){ echo();}virtual void echo() {cout << "DAD ";} };struct Son:Dad { public:void echo() const override…...

mac下安装tomcat

1. 官网下载Apache Tomcat - Apache Tomcat 9 Software Downloads 2. 授权bin目录下所有.sh文件权限sudo chmod 755 *.sh 3. 启动程序(后台运行) sudo sh ./startup.sh 4. 在当前窗口启动程序&#xff0c;随时看到日志sudo sh ./catalina.sh run 5. 关闭程序 sudo sh ./shu…...

【小梦C嘎嘎——启航篇】string常用接口的模拟实现

【小梦C嘎嘎——启航篇】string常用接口的模拟实现&#x1f60e; 前言&#x1f64c;string 模拟实现1、iterator 迭代器相关使用函数实现2、构造函数接口实现3、 传统写法——拷贝构造函数接口实现4、 现代写法——拷贝构造函数接口实现5、析构函数接口实现6、传统写法—— 赋…...

3个步骤掌握Markmap:将Markdown转换为交互式思维导图完全指南

3个步骤掌握Markmap&#xff1a;将Markdown转换为交互式思维导图完全指南 【免费下载链接】markmap Build mindmaps with plain text 项目地址: https://gitcode.com/gh_mirrors/ma/markmap Markmap作为一款强大的开源工具&#xff0c;能够将普通的Markdown文本转换为直…...

阿里开源Z-Image镜像体验:ComfyUI可视化生成汉服美女实战

阿里开源Z-Image镜像体验&#xff1a;ComfyUI可视化生成汉服美女实战 1. 开篇&#xff1a;当汉服遇见AI绘画 想象一下&#xff0c;你只需要输入"一位穿着汉服的中国女性站在樱花树下"&#xff0c;AI就能在几秒钟内生成一张细节精致的写实风格图像。这不再是科幻场景…...

PFC(5.0)模拟:GBM模型(grain- based model ) pb-sj或pb-...

PFC(5.0)模拟:GBM模型&#xff08;grain- based model &#xff09; pb-sj或pb-pb 单轴压缩。 模拟花岗岩等矿物晶体岩石&#xff0c;多种矿物晶体模型&#xff0c;其中矿物种类 数量分布可以自定义。 可以监测sj裂纹&#xff0c;和各矿物内裂纹。PFC5.0的GBM模型玩岩石破裂是真…...

Wan2.2-I2V-A14B效果对比:LSTM时序预测辅助下的动态剧情生成

Wan2.2-I2V-A14B效果对比&#xff1a;LSTM时序预测辅助下的动态剧情生成 1. 引言 想象一下&#xff0c;当你输入一段文字描述&#xff0c;AI不仅能生成对应的视频&#xff0c;还能像专业导演一样把控剧情节奏和情感起伏。这正是Wan2.2-I2V-A14B结合LSTM时序预测技术带来的突破…...

Heritrix3源码深度解析:从CrawlURI到ProcessorChain的执行流程

Heritrix3源码深度解析&#xff1a;从CrawlURI到ProcessorChain的执行流程 【免费下载链接】heritrix3 Heritrix is the Internet Archives open-source, extensible, web-scale, archival-quality web crawler project. 项目地址: https://gitcode.com/gh_mirrors/he/herit…...

如何通过InstantClick事件回调实现精准的性能监控:开发者必备指南

如何通过InstantClick事件回调实现精准的性能监控&#xff1a;开发者必备指南 【免费下载链接】instantclick InstantClick makes following links in your website instant. 项目地址: https://gitcode.com/gh_mirrors/in/instantclick InstantClick是一款能让网站链接…...

Qwen3-VL:30B开源可部署优势展示:无需License、无调用限制、全链路私有化保障

Qwen3-VL:30B开源可部署优势展示&#xff1a;无需License、无调用限制、全链路私有化保障 1. 为什么你需要一个私有化的多模态大模型&#xff1f; 想象一下这个场景&#xff1a;你的团队需要处理大量产品图片&#xff0c;并生成对应的营销文案。你打开某个在线AI工具&#xf…...

56:L构建蓝队AI:蓝队的智能防御

作者&#xff1a; HOS(安全风信子) 日期&#xff1a; 2026-03-07 主要来源平台&#xff1a; GitHub 摘要&#xff1a; 面对基拉等高级威胁的不断进化&#xff0c;传统的蓝队防御手段已经难以应对。L构建了一套蓝队AI系统&#xff0c;通过AI驱动的威胁检测、自动响应和防御优化&…...

SDMatte多风格抠图作品集:从商品白底图到艺术创意合成

SDMatte多风格抠图作品集&#xff1a;从商品白底图到艺术创意合成 1. 开篇&#xff1a;当抠图遇上AI 还记得那些年用Photoshop一点一点抠图的痛苦经历吗&#xff1f;边缘总是处理不干净&#xff0c;头发丝永远抠不完整&#xff0c;遇到复杂背景更是让人抓狂。现在&#xff0c…...

Hunyuan-MT-7B-WEBUI新手必看:5分钟搞定部署,开启多语言翻译之旅

Hunyuan-MT-7B-WEBUI新手必看&#xff1a;5分钟搞定部署&#xff0c;开启多语言翻译之旅 1. 为什么选择Hunyuan-MT-7B-WEBUI 在全球化交流日益频繁的今天&#xff0c;语言障碍成为许多个人和团队面临的实际问题。Hunyuan-MT-7B-WEBUI作为腾讯混元开源系列中的翻译专用模型&am…...