Synchronized你又知道多少?

简介: Synchronized 是 JVM 实现的一种互斥同步机制,通过 monitorenter 和 monitorexit 指令控制对象锁的获取与释放。锁的本质是对象头的标记,确保同一时间只有一个线程访问资源。Synchronized 支持可重入性,允许方法内部调用其他同步方法而不阻塞。JVM 对锁进行了优化,引入了自旋锁、偏向锁、轻量级锁和重量级锁,以减少系统开销。Synchronized 属于悲观锁,而乐观锁基于 CAS(Compare and Swap)算法实现非阻塞同步,提高并发性能。

Synchronized的底层原理是什么

Synchronized 是由JVM实现的一种实现互斥同步的一种方式,如果你查看被Synchronized修饰过的程序块编译后的字节码,会发现,被Synchronized修饰过的程序块,在编译前后被编译器生成了monitorenter和monitorexit两个字节码指令。


在虚拟机执行到monitorenter指令时,首先要尝试获取对象的锁:如果这个对象没有锁定,或者当前线程已经拥有了这个对象的锁,把锁的计数器+1;


当执行monitorexit 指令时将锁计数器-1;当计数器为0时,锁就被释放了。

如果获取对象失败了,那当前线程就要阻塞等待,直到对象锁被另外一个线程释放为止。

Java中Synchronize 通过在对象头设置标记,达到了获取锁和释放锁的目的。


锁的底层实现又是什么

锁”的本质其实是 monitorenter 和 monitorexit 字节码指令的一个Reference类型的参数,即要锁定和解锁的对象。我们知道,使用Synchronized 可以修饰不同的对象,因此,对应的对象锁可以这么确定。说明加解锁对象为该对象

1.如果 Synchronized 明确指定了锁对象,比如 Synchronized(变量名)、Synchronized(this)等

2.如果没有明确指定:若 Synchronized 修饰的方法为非静态方法, 表示此方法对应的对象为锁对象;

                                若 Synchronized 修饰的方法为静态方法, 则表示此方法对应的类对象为锁对象。

注意:当一个对象被锁住时,对象里面所有用 Synchronized 修饰的方法都将产生堵塞,而对象里非 Synchronized 修饰的方法可正常被调用, 不受锁影注意。


什么是可重入性,为什么Synchronized是可重入锁

可重入性是锁的一个基本要求,是为了解决自己锁死自己的情况。比如一个类中的同步方法调用另一个同步方法,假如Synchronized 不支持重入,进入method2方法时当前线程获得锁,method2方法里面执行method1 时当前线程又要去尝试获取锁,这时如果不支持重入,"它就要等释放,把自己阻塞,导致自己锁死自己。

对Synchronized来说,可重入性是显而易见的,刚才提到,在执行monitorenter 指令时,如果这个对象没有锁定,或者当前线程已经拥有了这个对象的锁(而不是已拥有了锁则不能继续获取)

其实本质上就通过这种方式实现了可重入性。


JVM对Java的原生锁做了哪些优化

在Java6之前,Monitor的实现完全依赖底层操作系统的互斥锁来实现,由于Java层面的线程与操作系统的原生线程有映射关系,如果要将一个线程进行阻塞在Java6之前,或唤起都需要操作系统的协助,这就需要从用户态切换到内核态来执行,这种切换代价十分昂贵,很耗处理器时间,现代IDK中做了大量的优化。

一种优化是使用自旋锁,即在把线程进行阻塞操作之前先让线程自旋等待一段时间,可能在等待期间其他线程已经解锁,这时就无需再让线程执行阻塞操作。避免了用户态到内核态的切换。

现代JDK中还提供了三种不同的Monitor实现,也就是三种不同的锁:

1.偏向锁(BiasedLocking)

2.轻量级锁

3.重量级锁

这三种锁使得JDK得以优化Synchronized的运行,当M检测到不同的竞争状况时,会自动切换到适合的锁实现,这就是锁的升级、降级。

1.当没有竞争出现时,默认会使用JVM会利用CAS操作,在对象头上的MarkWord部分设置线程ID,以表示这个对象偏向于当前线程,所以并不涉及真正的互斥锁,因为在很多应用场景中,大部分对象生命周期中最多会被一个线程锁定,使用偏斜锁可以降低无竞争开销。

2.如果有另一线程试图锁定某个被偏斜过的对象,JVM就撤销偏斜锁,切换到轻量级锁实现。

3.轻量级锁依赖CAS操作MarkWord来试图获取锁,如果重试成功,就使用普通的轻量级锁;否则,进一步升级为重量级锁。


为什么Synchronized是悲观锁,乐观锁又是什么,CAS又是什么

Synchronized显然是一个悲观锁,因为它的并发策略是悲观的:不管是否会产生竞争,任何的数据操作都必须要加锁、用户态核心态转换、维护锁计数器和检查是否有被阻塞的线程需要被唤醒等操作。

随着硬件指令集的发展,我们可以使用基于冲突检测的乐观并发策略。先进行操作,如果没有其他线程征用数据,那操作就成功了;如果共享数据有征用,产生了冲突,那就再进行其他的补偿措施。

这种乐观的并发策略的许多实现不需要线程挂起,所以被称为非阻塞同步。

乐观锁的核心算法是CAS(Compareandswap,比较并交换),它涉及到三个操作数:内存值、预期值、新值。

当且仅当预期值和内存值相等时才将内存值修改为新值。

这样处理的逻辑是,首先检查某块内存的值是否跟之前我读取时的一样,如不一样则表示期间此内存值已经被别的线程更改过,舍弃本次操作,否则说明期间没有其他线程对此内存值操作,可以把新值设置给此块内存。

CAS具有原子性,它的原子性由CPU硬件指令实现保证,即使用INI调用Native方法调用由C++编写的硬件级别指令,JDK中提供了Unsafe类执行这些操作

相关文章
|
Java 数据安全/隐私保护 Spring
SpringSecurity6从入门到实战之SpringSecurity整合自动装配详解(源码级别讲解,耐心)
该内容是关于SpringSecurity在SpringBoot中的自动配置详解。文章首先提出问题:SpringSecurity如何在引入依赖后使所有请求需认证并显示登录表单。接着,它探讨了SpringBoot的自动装配原理,从@SpringBootApplication注解开始,深入到@EnableAutoConfiguration的实现,解释了如何通过扫描jar包中的.imports文件来加载自动配置类。特别提到了SpringBootWebSecurityConfiguration类,该类默认设置为对所有请求进行认证,并支持表单和Basic认证。
|
Java
Java @Data 注解详细说明
Data注解是 Lombok 提供的一个组合注解,它会为类自动生成一些常见方法的样板代码,包括 getter、setter、equals、hashCode 和 toString 方法。
3543 5
|
机器学习/深度学习 负载均衡 Java
【SpringBoot系列】微服务远程调用Open Feign深度学习
【4月更文挑战第9天】微服务远程调度open Feign 框架学习
1091 2
|
Java
Java基础知识总结(超详细整理)
本文系统总结Java基础知识,涵盖语法、面向对象(类与对象、封装、继承、多态)、常用类(String、包装类、集合框架)及异常处理等核心内容,结合代码示例深入浅出,助你扎实掌握Java编程基础。
867 1
|
9月前
|
人工智能 关系型数据库 数据库
从零到一:向量数据库到底在存什么?大模型开发者必备指南
本文用生活化语言揭秘向量数据库:它是大模型的“超级图书馆”,将文本、图像等转为数字向量(如苹果→[1,1,1,1]),实现语义相似检索。详解RAG知识库构建三步法——切片、向量化、检索增强,并对比传统数据库,强调其“找相似”而非“找精确”的核心价值。
1026 2
|
存储 机器学习/深度学习 人工智能
46_LLM幻觉问题:来源与早期研究_深度解析
大型语言模型(LLM)在自然语言处理领域展现出了令人惊叹的能力,能够生成连贯的文本、回答复杂问题、进行创意写作,甚至在某些专业领域提供见解。然而,这些强大模型的一个根本性缺陷——幻觉问题,正成为限制其在关键应用中广泛部署的主要障碍。幻觉(Hallucination)指的是LLM生成的内容与事实不符、上下文矛盾、逻辑错误,或者完全虚构信息的现象。
1058 0
|
开发框架 Java .NET
【App Service】Java应用上传文件功能部署在App Service Windows上报错 413 Payload Too Large
Java应用在Azure App Service(Windows)部署时,因IIS默认限制上传文件不超过30MB,导致大文件上传出现413错误。虽无web.config文件,可通过Kudu工具手动创建并配置maxAllowedContentLength和maxRequestLength,突破限制,实现大文件上传。
484 3
|
SQL XML Java
Mybatis基础使用知识(注解)
mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句。 最后 mybatis 框架执行sql 并将结果映射为java对象并返回。采用ORM(对象关系映射)思想解决了实体和数据库映射问题,对jdbc进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api 打交道,就可以完成对数据库的持久化操作。
674 0
|
监控
【多线程:interrupt 方法详解】
【多线程:interrupt 方法详解】
565 0
|
存储 安全 网络安全
蜜罐技术:如何跟踪攻击者的活动
【10月更文挑战第22天】蜜罐是一种用于网络安全的系统,通过模拟漏洞吸引攻击者,记录其行为以研究攻击手法。分为高交互和低交互两种类型,前者提供真实操作系统服务,后者仅模拟部分系统功能。蜜罐有助于收集恶意软件样本,分析攻击者行为,提高网络安全防御。
759 3