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

Synchronized 概述


1. 初识

synchronized 是 Java 中的关键字,是一种 同步锁可重入锁悲观锁。它修饰的对象有以下几种:
具体表现为以下3种形式。
对于普通同步方法,锁是当前实例对象。
对于静态同步方法,锁是当前类的 Class 对象。
对于同步方法块,锁是 synchonized 括号里配置的对象。

虽然可以使用 synchronized 来定义方法,但 synchronized 并不属于方法定义的一部分,因此,synchronized
关键字不能被继承。 如果在父类中的某个方法使用了 synchronized 关键字,而在子类中覆盖了这个方法,在子类中的这
个方法默认情况下并不是同步的,而必须显式地在子类的这个方法中加上 synchronized
关键字才可以。当然,还可以在子类方法中调用父类中相应的方法,这样虽然子类中的方法本身不是同步的,但子类调用了父类的同步方法,因此,子类的方法也就相当于同步了。

如果一个代码块被 synchronized 修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待持有锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况

  1. 获取锁的线程执行完了该代码块,然后线程释放对锁的占有;
  2. 线程执行发生异常,此时 JVM 会让线程自动释放锁。

那么如果这个获取锁的线程由于要等待 IO 或者其他原因(比如调用 sleep
方法)被阻塞了,但是又没有释放锁,其他线程便只能干巴巴地等待,试想一下,这多么影响程序执行效率。
因此就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间或者能够响应中断),通过 Lock 就可以办到。


2. synchronized 的底层字节码

synchronized 三种用法及其原理

2.1 同步代码块

通过反编译可以看到, 其实现使用的是 monitorenter 和 monitorexit 指令。

2.2 普通同步方法

在这里插入图片描述

调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置。如果设置了,执行线程会将先持有 monitor 然后再执行方法,最后在方法完成(正常和异常情况都算完成)时释放 monitor。

2.3 类同步方法

在这里插入图片描述

ACC_STATIC 和 ACC_SYNCHRONIZED 访问标志区分该方法是否是静态同步方法。


3. synchronized 锁的是什么

synchronized 用的锁是存在 Java 对象头里的。

3.1 什么是管程

管程 (英语:Monitors,也称为监视器) 是一种程序结构,结构内的多个子程序(对象或模块)形成的多个工作线程互斥访问共享资源。
这些共享资源一般是硬件设备或一群变量。对共享变量能够进行的所有操作集中在一个模块中。(把信号量及其操作原语“封装”在一个对象内部)管程实现了在一个时间点,最多只有一个线程在执行管程的某个子程序。管程提供了一种机制,管程可以看做一个软件模块,它是将共享的变量和对于这些共享变量的操作封装起来,形成一个具有一定接口的功能模块,进程可以调用管程来实现进程级别的并发控制。

在这里插入图片描述

3.2 monitor ObjectMonitor

在 HotSpot 虚拟机中, monitor 采用 ObjectMonitor 实现
ObjectMonitor.java ->> ObjectMonitor.cpp ->> ObjectMonitor.hpp

在这里插入图片描述

Java 中的每个对象天生都带着一个对象的监视器(所以 Java 中任何一个对象都可以成为一个锁)。
任何对象都有一个 monitor 与之关联,当且一个 monitor 被持有后,它将处于锁定状态。线程执行到 被 synchronized 修饰的方法时,将会 尝试获取对象头的 monitor 的所有权,即尝试获得对象的锁。

http://www.xdnf.cn/news/19503.html

相关文章:

  • 平衡二叉树(一)
  • 2016考研数学(二)真题
  • sunset: noontide靶场
  • AlphaFold 2 本地部署与安装教程(Linux)
  • 高速CANFD通讯接口芯片ASM1042性能分析与5Mbps多节点测验
  • 包的相对导入
  • MPI-NCCL-TEST 训练自检,基础通信和可用的机器
  • 《Bishop PRML》10.1 (3) 理解VAE KL loss
  • 【贪心算法】day5
  • PPO、DPO和GRPO的区别
  • Python实现BP神经网络
  • 利用美团longcat.ai编写的C语言支持指定压缩算法通用ZIP压缩程序
  • 硬件工程师成长之路:从入门到精通的技术旅程
  • 科学研究系统性思维的方法体系:研究设计相关模版
  • go 开发环境配置 air + dlv debug 踩坑之旅
  • Linux shell 脚本基础 003
  • C6.7:输入电阻的负载效应及其CE负反馈放大器
  • android-studio 安装
  • Mysql中事务隔离级别有哪些?
  • Java实习:MySQL篇(黑马JavaWeb课程)
  • 简单的加密算法
  • PostgreSQL表膨胀的危害与解决方案
  • 人工神经网络(ANN)深度学习
  • 开源 C++ QT Widget 开发(九)图表--仪表盘
  • dayjs ​JavaScript 时间日期处理库
  • P2P技术应用:去中心化
  • Java全栈开发面试实战:从基础到微服务的全面解析
  • NAS Docker 安装N8N
  • 鸿蒙ArkTS 核心篇-18-@Builder 自定义构建函数
  • 上海交大具身导航中的感知智能、社会智能和运动智能全面综述