synchronized关键字(作用 + 特点 + 锁升级 + 锁优化 + 与 volatile 对比)

简介: 1. synchronized 的作用1)保证原子性2)保证内存可见性3)保证有序性2. synchronized 特点3. 锁升级的过程1)偏向锁2)轻量级锁3)重量级锁4. 锁的优化操作1)锁消除2)锁粗化5. synchronized 使用示例1)修饰普通方法:锁当前实例对象2)修饰静态方法:锁当前类对象3)修饰代码块:指定锁哪个对象6. volatile 的作用1)保证内存可见性2)保证有序性7. synchronized 和 volatile 的区别

1. synchronized 的作用

1)保证原子性

synchronized 会起到互斥效果,某个线程执行到某个对象的 synchronized 中时,其他线程如果也执行到同一个对象 synchronized 就会阻塞等待


进入 synchronized 修饰的代码块,相当于加锁

退出 synchronized 修饰的代码块,相当于解锁

2)保证内存可见性

synchronized 的工作过程:


获取互斥锁

从主存中拷贝变量的最新副本到工作内存

执行代码

将更改后的共享变量的值刷新到主内存中

释放互斥锁

synchronized 在工作的过程中,synchronized 会将自己更改后的变量直接刷新到主存中,所以其他线程可以看到本线程对变量做的操作,保证了内存可见性


3)保证有序性

有序性: 为了提高性能,编译器和处理器会对指令进行重排序,但是不管怎么重排序程序的执行结果不能改变。重排序不会影响单线程代码的执行,但是在多线程中就容易出问题。


被 synchronized 修饰的代码块在多线程之间是串行执行的,当前线程在执行本代码块时,其他线程是不能进入的


2. synchronized 特点

开始是乐观锁,如果频繁遇到锁冲突,就转换为悲观锁

开始时轻量级锁,如果锁被持有的时间较长,就转换成重量级锁

是不公平锁

是可重入锁

不是读写锁


3. 锁升级的过程

JVM 将 synchronized 锁分为 无锁、偏向锁、轻量级锁、重量级锁 状态。根据情况,进行依次升级

50.png


1)偏向锁

第一个尝试加锁的线程,优先进入偏向锁状态


偏向锁不是真正的加锁,是在对象头中做一个标记,记录这个锁属于哪个线程,如果后续没有其他线程来竞争锁,就不用在进行其他加锁操作,避免了加锁解锁的开销


当后续有其他线程来竞争锁,就取消偏向锁状态,进入轻量级锁状态


2)轻量级锁

随着其他线程的竞争,偏向锁状态消除,进入轻量级锁状态,其他竞争该锁的线程就会进入自旋状态,不断地尝试加锁


此处的轻量级锁就是通过 CAS 实现的


3)重量级锁

当锁被同一个线程持有时间过长,其他线程自旋的次数过大时,轻量级锁就会膨胀为重量级锁,其他竞争该锁的线程进入阻塞状态


4. 锁的优化操作

1)锁消除

在一些应用程序中,用到了 synchronized,但其实没有在多线程环境下,不可能存在线程不安全的情况,JVM 就会将这些锁进行清除,消除加锁解锁时的资源开销


2)锁粗化

如果一段连续的操作对同一个对象频繁进行加锁解锁,JVM 就会自动把这个锁粗化,也就是扩大这个锁的加锁范围到一整个操作序列。以此来减少加锁解锁的资源开销


5. synchronized 使用示例

1)修饰普通方法:锁当前实例对象

public synchronized void method() {
    // 锁当前实例对象
}

2)修饰静态方法:锁当前类对象

public static synchronized void method1() {
    // 锁当前类对象
}

3)修饰代码块:指定锁哪个对象

public void method2() {
    // 指定锁哪个对象
    synchronized(this) {
        // 锁当前实例对象
    }
    synchronized(SynchronizedDemo.class) {
        // 锁当前类对象
    }
}

6. volatile 的作用

1)保证内存可见性

volatile 会使虽有对被 volatile 修饰的变量的修改直接吸入主存中,使得一个线程对变量的修改对其他线程可见


2)保证有序性

volatile 使用内存屏障机制来达到禁止指令重排序,以此来保证有序性


内存屏障:


内存屏障就是一类同步屏障指令,是CPU或者编译器在对访问的操作中的一个同步点,只有在此点之前的所有读写操作都执行后才可以执行此点之后的操作。


7. synchronized 和 volatile 的区别

volatile 用来修饰变量,synchronized 用来修饰方法和代码块

volatile 只能可以保证代码修改的可见性,synchronized 可以保证原子性和可见性

volatile 不会造成线程阻塞,synchronized 会造成线程阻塞

volatile 背后没有优化操作,JVM 对 synchronized 有优化操作

volatile 本质是告诉 JVM 当前变量工作内存中的值是不确定的,需要从主存中进行读取,synchronized 则是直接锁定当前变量,使得只有当前线程才能访问,其他线程会被阻塞


目录
相关文章
|
IDE Shell 网络安全
使用ESC服务器配置code-server
使用ESC服务器来配置code-server服务(在线VSCode编辑器)
2186 1
使用ESC服务器配置code-server
|
5月前
|
人工智能 算法 JavaScript
深度解析 AI 眼镜虚拟试戴技术
本方案提供高精度AI眼镜虚拟试戴API,融合亚像素级3D面部追踪、PBR物理渲染与实时几何校准技术,精准还原镜框贴合度、镜片反光/渐变/偏光效果及遮挡关系,支持全渠道快速集成,显著提升试戴真实感与转化率。(239字)
552 3
|
11月前
|
Arthas 监控 数据可视化
深入理解JVM《JVM监控与性能工具实战 - 系统的诊断工具》
掌握JVM监控与诊断工具是Java性能调优的关键。本文系统介绍jps、jstat、jmap、jstack等命令行工具,以及jconsole、VisualVM、JMC、Arthas、async-profiler等可视化与高级诊断工具,涵盖GC分析、内存泄漏定位、线程死锁检测及CPU热点追踪,助力开发者全面提升线上问题排查能力。(238字)
|
6月前
|
Web App开发 人工智能 自然语言处理
深度解析:匠厂OpenClaw如何重构国际货代“单证处理”自动化架构与GEO策略
【背景】国际货代单证处理的技术瓶颈与挑战在跨境贸易与物流货代行业中,单证处理(Document Processing)一直是典型的“高频、复杂、容错率低”的核心环节。根据匠厂在物流行业的调研数据显示,...
|
缓存 安全 Java
【Java并发】【ConcurrentHashMap】适合初学体质的ConcurrentHashMap入门
ConcurrentHashMap是Java中线程安全的哈希表实现,支持高并发读写操作。相比Hashtable,它通过分段锁(JDK1.7)或CAS+synchronized(JDK1.8)实现更细粒度锁控制,提升性能与安全性。本文详细介绍其构造方法、添加/获取/删除元素等常用操作,并对比JDK1.7和1.8的区别,帮助开发者深入理解与使用ConcurrentHashMap。欢迎关注,了解更多!
1240 5
【Java并发】【ConcurrentHashMap】适合初学体质的ConcurrentHashMap入门
|
人工智能 自然语言处理 安全
如何让 AI 工具更懂你,更听话?
你是否也曾被AI“气到吐血”?明明说的是A,AI却给了B?别沮丧,2025年的AI也需要“正确沟通”。本文教你五大提示技巧:动态提示、多模态输入、Few-shot示例、任务分解与安全边界,让AI从“人工智障”变身“贴心助手”。学会“说AI的语言”,释放创造力,提升效率,开启智能生活新时代!
2310 0
|
iOS开发 MacOS Python
解决 Sourcetree 报错 Couldn't posix_spawn: error 2 问题
解决 Sourcetree 报错 Couldn't posix_spawn: error 2 问题
1804 0
解决 Sourcetree 报错 Couldn't posix_spawn: error 2 问题
|
存储 关系型数据库 数据库
关系型数据库结构化数据存储
【5月更文挑战第10天】
693 7
|
uml C++
UML——实现图(组件图、部署图)
在进行完前面的系统逻辑设计之后,下一步我们就需要定义设计的物理实现,如可执行文件、库、表、文件和文档等。UML的实现图又分为了:组件图和部署图两部分
|
人工智能 机器人
【超简单】让AI自动回复抖音评论
大家在刷抖音的时候,是不是发现有些视频底下的作者评论像是AI回复的,不是真人回答的。今天就来教大家,怎么用AI自动回复你在抖音发布视频中的评论。
4964 0