浅谈synchronized锁原理

简介: 保证线程安全的一个重要手段就是通过加锁的形式实现,今天盘点一下Java中锁的八股文

Java相关文章



线程安全

  1. 当多个线程同时共享,同一个全局变量或者静态变量,做写的操作时,可能会发生数据冲突问题
  2. 为了避免出现线程安全在必要的时候需要牺牲性能使用锁来保证。


Object监视器模型

  1. 锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。
  2. 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中
  3. 类比AQS中的同步队列与条件队列


synchronized锁原理

  1. Java对象存储在堆中,主要分为三部分,对象头、对象实例数据和对齐补充
  2. 每个对象都有一个与之关联的Monitor 对象存在对象头中
  3. 线程拿锁的过程
  1. 将被锁对象中的 _owner设置成A线程
  2. 所有请求锁的线程首先被放在ContentionList这个竞争队列中;
  3. Contention List 中那些有资格成为候选资源的线程被移动到 Entry List 中;
  4. 任意时刻,最多只有一个线程正在竞争锁资源,该线程被成为 OnDeck;
  5. 当前已经获取到所资源的线程被称为 Owner;


synchroized的锁升级过程

  1. 锁级别由低到高分别是
  1. 无锁
  2. 偏向锁
  3. 轻量级锁
  4. 重量级锁
  1. 升级过程
  1. 线程A在进入同步代码块前,先检查MarkWord中的线程ID是否与当前线程ID一致,如果一致(还是线程A获取锁对象),则无需使用CAS来加锁、解锁
  2. 如果不一致,再检查是否为偏向锁,如果不是,则自旋等待锁释放
  3. 如果是,再检查该线程是否存在(偏向锁不会主动释放锁),如果不在,则设置线程ID为线程A的ID,此时依然是偏向锁。
  4. 如果还在,则暂停该线程,同时将锁标志位设置为00即轻量级锁(将MarkWord复制到该线程的栈帧中并将MarkWord设置为栈帧中锁记录)。线程A自旋等待锁释放。
  5. 如果自旋次数到了该线程还没有释放锁,或者该线程还在执行,线程A还在自旋等待,这时又有一个线程B过来竞争这个锁对象,那么这个时候轻量级锁就会膨胀为重量级锁。重量级锁把除了拥有锁的线程都阻塞,防止CPU空转。
  6. 如果该线程释放锁,则会唤醒所有阻塞线程,重新竞争锁
  1. 根据不同情况也会降级


synchronized锁的范围

  1. 锁是加在对象上面的,我们是在对象上加锁
  2. 锁的标记是记录在对象头中、synchronized原理最终是在代码中加入monitorenter和monitorexit这两个字节码指令保证代码的同步,所以锁的是对象


作用范围

锁对象

非静态方法

当前对象 => this

静态方法

Class对象 => SynchronizedSample.class (一切皆对象,这个是类对象)

代码块

指定对象 => 可以Synchronized(this),也可以Synchronized(Class对象)

相关文章
|
存储 搜索推荐 人机交互
Qt鼠标事件全面解析:从基础到实战
Qt鼠标事件全面解析:从基础到实战
2331 0
|
JSON PHP 开发工具
PHP Monolog 日志的使用
PHP Monolog 日志的使用
1144 0
|
Android开发
Android 13 Qs面板的加载流程
Android 13 Qs面板的加载流程
1519 0
Android 13 Qs面板的加载流程
|
存储 网络架构
Next.js 实战 (四):i18n 国际化的最优方案实践
这篇文章介绍了Next.js国际化方案,作者对比了网上常见的方案并提出了自己的需求:不破坏应用程序的目录结构和路由。文章推荐使用next-intl库来实现国际化,并提供了详细的安装步骤和代码示例。作者实现了国际化切换时不改变路由,并把当前语言的key存储到浏览器cookie中,使得刷新浏览器后语言不会失效。最后,文章总结了这种国际化方案的优势,并提供Github仓库链接供读者参考。
578 0
Next.js 实战 (四):i18n 国际化的最优方案实践
|
10月前
|
机器学习/深度学习 人工智能 监控
AI视频监控技术的核心优势与实践
AI视频监控技术结合了计算机视觉、深度学习和大数据分析,能够实时分析监控画面,识别异常行为和场景变化。其核心在于从“被动记录”转型为“主动识别”,提升监控效率并减少安全隐患。主要应用场景包括泳池管理、健身器械区域、人员密度预警和异常事件检测。系统架构支持多种摄像头设备,采用边缘计算和Docker部署,具备实时性、高准确率和扩展性等优势。未来将优化复杂场景适应性和实时计算负载,进一步提高系统性能。
2236 7
|
消息中间件 安全 Java
线程和进程的区别及应用场景
线程和进程的区别及应用场景
|
12月前
|
IDE Java 测试技术
通义灵码测评报告
通义灵码测评报告
653 1
|
编解码 Linux 开发工具
Linux平台x86_64|aarch64架构RTMP推送|轻量级RTSP服务模块集成说明
支持x64_64架构、aarch64架构(需要glibc-2.21及以上版本的Linux系统, 需要libX11.so.6, 需要GLib–2.0, 需安装 libstdc++.so.6.0.21、GLIBCXX_3.4.21、 CXXABI_1.3.9)。
371 0
|
SQL 运维 Java
SpringBoot集成Flyway
Flyway:官方解释:Flyway 将 DevOps 扩展到您的数据库,以加速软件交付并确保代码质量。从版本控制到持续交付,Flyway 以应用程序交付流程为基础,实现数据库部署自动化。 官方解释总是那么拗口和不说人话,当然通过加粗的关键字我们基本也能够了解到Flyway的功能特性。 通俗来说,Flyway可以作为数据库迁移工具服务到我们的应用程序升级发布流程中,减少人为处理sql脚本带来的繁琐和易出错问题。 例如,当我们的一个业务微服务从1.5.0升级到1.5.1的时候涉及到数据库的改动(DDL、DML)可以交给Flyway处理,我们无需关心。
1548 0
|
存储 安全 Java
synchronized原理详解(通俗易懂超级好)
当系统检查到锁是重量级锁之后,会把等待想要获得锁的线程进行阻塞,被阻塞的线程不会消耗cpu。但是阻塞或者唤醒一个线程时,都需要操作系统来帮忙,这就需要从用户态转换到内核态,而转换状态是需要消耗很多时间的,有可能比用户执行代码的时间还要长。
synchronized原理详解(通俗易懂超级好)