一文弄懂synchronized

news2024/11/29 8:35:07

简述

synchronized是什么?

synchronized 关键字是一种同步锁,它可以保证在一个时刻只有一个线程可以执行某段代码。synchronized 关键字可以用在方法、代码块、静态方法和静态代码块上。

synchronized怎么用?

synchronized是Java中用于实现线程同步的关键字,它可以修饰方法或代码块。

  1. 修饰方法:当一个方法被synchronized修饰时,表示该方法是一个同步方法。同一时间只能有一个线程执行该方法,其他线程需要等待。
public synchronized void method() {
  // 这里是同步代码块
}
  1. 修饰代码块:当一个代码块被synchronized修饰时,表示该代码块是一个同步代码块。同一时间只能有一个线程进入该代码块,其他线程需要等待。
public class Example {

    public static void main(String[] args) {
        final int[] number = {1, 2, 3, 4, 5};

        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                synchronized (number) {
                    // 这里是同步代码块
                    System.out.println(number[i]);
                }
            }).start();
        }
    }
}

锁的是什么

普通同步方法>锁的是当前实力对象。
静态同步方法>锁的是当前类的Class对象。
同步方法快>锁的是synchonized括号里配置的对象。

注意事项

当使用synchronized修饰代码块时,应该尽量控制同步代码块的范围,避免锁的竞争过于频繁,以提高程序的性能。同时,锁对象的选择也很重要,应该选择合适的锁对象以避免不必要的线程等待和资源竞争。

原理

synchronized修饰代码块和方法的底层原理类似,都是通过对象头中的锁标记位来实现的。

修饰方法

进入方法:当线程调用一个被synchronized修饰的方法时,会尝试获取该方法所属对象的锁。
获取锁:如果对象的锁标记位为"unlocked"状态,则当前线程可以获取到锁,并将锁标记位设置为"locked"状态,表示该对象被当前线程锁定。
执行方法体:线程获取到锁后,会执行synchronized修饰的方法体中的代码。
释放锁:当方法执行完毕或抛出异常时,会自动释放对象的锁,将锁标记位重新设置为"unlocked"状态。

注意点

需要注意的是,synchronized修饰方法时,默认锁定的是当前对象实例(this),即当前方法所属的对象。如果是静态方法,锁定的是当前类的Class对象。

//1.静态方法 
public static synchronized void method() {
    // 该方法被当前类的Class对象锁定
    // ...
}
//2.普通方法
public synchronized void method() {
    // 该方法被当前实例对象锁定
    // ...
}

修饰代码块

进入代码块:当线程进入一个被synchronized修饰的代码块时,会尝试获取对象的锁。
获取锁:如果对象的锁标记位为"unlocked"状态,则当前线程可以获取到锁,并将锁标记位设置为"locked"状态,表示该对象被当前线程锁定。
阻塞或执行:如果对象的锁标记位为"locked"状态,表示该对象已被其他线程锁定。当前线程会被阻塞,直到锁标记位变为"unlocked"状态时才能继续执行。
释放锁:当线程执行完synchronized代码块后,会释放对象的锁,将锁标记位重新设置为"unlocked"状态,使其他线程能够获取到锁并执行。

public void method() {
    synchronized (lock) {
        // 该代码块被lock对象锁定
        // ...
    }
}

锁的高级特征

JVM在实现锁的过程中采用了多种锁的机制,包括偏向锁、轻量级锁和重量级锁,并且会根据锁竞争的情况自动进行锁升级和降级。下面是对这些锁的机制和锁升级的简要说明:

偏向锁(Bias Locking):

简介

偏向锁是一种乐观锁策略,适用于大部分情况下只有一个线程对锁进行竞争的场景。
偏向锁的目标是减少无竞争的情况下对锁的开销,提高程序的性能。
当一个线程获取到偏向锁后,JVM会将线程的标识记录在对象头中,之后该线程再次获取锁时无需进行同步操作,从而提高了程序的执行效率。

实现原理

轻量级锁(Lightweight Locking):

简介

当多个线程对同一个锁进行竞争时,JVM会将锁升级为轻量级锁。
轻量级锁使用CAS(Compare and Swap)操作来实现对锁的获取和释放,避免了线程阻塞和唤醒的开销。
如果竞争激烈,多个线程同时尝试获取锁,那么轻量级锁会膨胀为重量级锁。

实现原理

重量级锁(Heavyweight Locking):

简介

当轻量级锁膨胀失败或竞争过于激烈时,JVM会将锁升级为重量级锁。
重量级锁使用操作系统的互斥量来实现对锁的获取和释放,需要涉及线程的阻塞和唤醒。
线程在获取重量级锁时会进入阻塞状态,当锁被释放时,JVM会从阻塞的线程中选择一个进行唤醒。
锁的升级和降级是根据锁竞争的情况动态进行的,以提高程序的性能和吞吐量。当JVM检测到锁竞争较少时,会尝试将重量级锁降级为轻量级锁,以提高并发性能。反之,如果锁竞争激烈,JVM会将轻量级锁膨胀为重量级锁,以避免不必要的自旋和消耗。

实现原理

需要注意的是,锁的升级和降级过程对于开发者来说是透明的,无需手动干预。JVM会根据实际情况自动进行锁的升级和降级操作,以达到更好的性能和可伸缩性。

这些锁的机制和锁升级是JVM内部的实现细节,对于开发者来说,只需要了解它们的存在和基本原理,以正确地使用synchronized关键字来实现线程安全的同步。

优秀文章传送门:
https://zhuanlan.zhihu.com/p/571793506
在这里插入图片描述

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

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

相关文章

最新Ai系统ChatGPT程序源码+以图生图+Dall-E2绘画+支持GPT4+Midjourney绘画

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

Spring Cloud之Seata的学习

目录 案例准备 分布式事务 基本理论 CAP定理 BASE理论 Seata 部署TC服务 数据库准备 修改Nacos配置并导入信息 启动Seata 集成Seata XA模式原理 Seata的XA实现 优点 缺点 实现 AT模式原理 AT模式的脏写问题 Seata的AT实现 XA与AT的区别 TCC模式原理 空回…

深度学习之基于Python+OpenCV+dlib的考生信息人脸识别系统(GUI界面)

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 深度学习在人脸识别领域的应用已经取得了显著的进展。Python是一种常用的编程语言&#xff0c;它提供了许多强大的库…

Python基础入门例程37-NP37 不低于与不超过(运算符)

最近的博文&#xff1a; Python基础入门例程36-NP36 谁的数字大&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程35-NP35 朋友的年龄是否相等&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程34-NP34 除法与取模运算&#xff08;运算符&#xff09;…

SpringSecurity全家桶 (二) ——实现原理

1. SpringSecurity的强大之处 当我们并未设置登录页面时&#xff0c;我们只需要导入SpringSecurity的依赖就可以令我们的界面进入保护状态&#xff0c;由下面例子可以凸显出&#xff1a; 随便写个接口 RequestMapping("/hello")public String hello(){return "H…

spring-boot中实现分片上传文件

一、上传文件基本实现 1、前端效果图展示&#xff0c;这里使用element-ui plus来展示样式效果 2、基础代码如下 <template><div><el-uploadref"uploadRef"class"upload-demo":limit"1":on-change"handleExceed":auto-…

PPT制作指南

诸神缄默不语-个人CSDN博文目录 文章目录 1. SOP2. PPT的目标3. PPT素材4. 内容框架5. 设计细节本文撰写过程中使用到的参考资料 1. SOP 分析目标→收集素材→明确框架→视觉呈现 2. PPT的目标 演讲型PPT&#xff1a;字少图多 阅读型PPT&#xff1a;需要文字解释 分析维度&…

shell学习脚本05(小滴课堂)

可以对海量的数据进行提取。 -v对提取的内容进行取反。 -n显示出行号。 -w精确匹配&#xff1a; -i:忽略大小写&#xff1a; -E正则匹配&#xff1a; cut命令&#xff1a; -d指定分隔符&#xff0c;-f指定截取区域&#xff1a; 截取第一列到第三列&#xff1a; 截取第二列到最…

一文带你了解如何让自动化测试框架更自动化

一、引言 ​对于大厂的同学来说&#xff0c;接口自动化是个老生常谈的话题了&#xff0c;毕竟每年的MTSC大会议题都已经能佐证了&#xff0c;不是大数据测试&#xff0c;就是AI测试等等&#xff08;越来越高大上了&#xff09;。不可否认这些专项的方向是质量智能化发展的方向…

第五章 Python文件操作

系列文章目录 第一章 Python 基础知识 第二章 python 字符串处理 第三章 python 数据类型 第四章 python 运算符与流程控制 第五章 python 文件操作 第六章 python 函数 第七章 python 常用内建函数 第八章 python 类(面向对象编程) 第九章 python 异常处理 第十章 python 自定…

SpringBoot框架使用AOP + 自定义注解实现请求日志记录

一、SpringBoot记录日志 文章目录 一、SpringBoot记录日志1.1、环境搭建1.2、配置FastJson1.3、自定义LogRecord注解1.4、定义日志实体类1.5、创建HttpRequestUtil工具类1.6、定义AOP切面1.7、编写测试类1.8、运行测试 1.1、环境搭建 搭建SpringBoot工程。引入【spring-boot-st…

Docker:Dockerfile语法

Docker&#xff1a;Dockerfile语法 1. 镜像2. 镜像结构3. Dockerfile 1. 镜像 前面我们一直在使用别人准备好的镜像&#xff0c;那如果我要部署一个Java项目&#xff0c;把它打包为一个镜像该怎么做呢&#xff1f; 2. 镜像结构 要想自己构建镜像&#xff0c;必须先了解镜像的…

【漏洞复现】IIS_7.o7.5解析漏洞

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证 1.5、修复建议 1.1、漏洞描述 漏洞原理&#xff1a; cgi.fix_path1 1.png/.php该…

送你几款开源IDC资产管理系统

更多运维技术&#xff0c;请关注微信公众号“运维之美” 送你几款开源IDC资产管理系统 1.phpIPAM2.NetBox3.IPPlan4.GestiIP5.RackTables 对于公司机房运维人员来说&#xff0c;你的idc资产管理清单可能还记录在各种excel表格中&#xff0c;当设备和ip变动的时候进行手动更新&a…

Java继承:抽取相同共性,实现代码复用

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、继承的概念二、继承的语法三、父类成员访问1、子类中访问父类成员变量Ⅰ、子类和父类不存在同名成员变量Ⅱ、子类和父类成员…

泄漏检测与修复(LDAR)过程管控平台(销售出租)VOCs便携式总烃分析仪(销售出租)

LDAR是Leak Detection and Repair&#xff08;泄漏检测与修复&#xff09;的缩写&#xff0c;也是国际上较先进的化工废气检测技术。LDAR主要通过检测化工企业原料输送管道、泵、阀门、法兰等易产生易产生挥发性有机物&#xff08;简称VOCs&#xff09;泄漏的部位&#xff0c;并…

turn.js 模版简单使用

turn.js 不修改添加原功能仅 替换、修改图片格式使用模版 HTML文件 turn.js官网&#xff1a;http://www.turnjs.com/# 第一步 1.点击链接去到官网 2.点击下载按钮 下载左侧示例压缩包 3.解压完成拿到示例文件 turnjs4 4.在samples目录下案例中查看意向使用的模版样式 …

OpenGL_Learn05(纹理)

1. 纹理贴图 wall.jpg (512512) (learnopengl-cn.github.io) 纹理过滤分为&#xff1a;邻近和线性&#xff0c;这跟opencv图像处理一样。 多级渐远纹理 四种采样方式&#xff1a; 代码实现&#xff1a; std_image.h https://github.com/nothings/stb/blob/master/stb_image.…

【数据结构】冒泡排序 (码源实现)

冒泡排序 前言一、冒泡排序运行图例二、算法实现基本思路三、算法实现步骤四、算法码源详解五、冒泡排序效率分析&#xff08;一&#xff09;时间复杂度——O&#xff08;N^2&#xff09;&#xff08;二&#xff09;空间复杂度——O&#xff08;1&#xff09;&#xff08;三&am…

【PC电脑windows-学习样例tusb_serial_device-ESP32的USB模拟串口程序+VScode建立工程+usb组件添加+-基础样例学习】

【PC电脑windows-学习样例tusb_serial_device-ESP32的USB模拟串口程序-基础样例学习】 1、概述2、实验环境3-1、 物品说明3-2、所遇问题&#xff1a;ESP32 cannot open source file "tinyusb.h"或者“tinyusb.h:No such file or directory ....”3-3、解决问题&#…