浅谈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鼠标事件全面解析:从基础到实战
2109 0
|
监控 测试技术 网络安全
基于阿里云计算巢部署的幻兽帕鲁服务器我该如何设置计划任务定时备份和重启,以及存档导入导出
基于阿里云计算巢部署的幻兽帕鲁服务器我该如何设置计划任务定时备份和重启,以及存档导入导出
|
Android开发
Android 13 Qs面板的加载流程
Android 13 Qs面板的加载流程
1467 0
Android 13 Qs面板的加载流程
|
消息中间件 安全 Java
线程和进程的区别及应用场景
线程和进程的区别及应用场景
|
9月前
|
人工智能 自然语言处理 算法
几款宝藏级AI阅读工具推荐!论文分析、文档总结必备神器!
【10月更文挑战第8天】几款宝藏级AI阅读工具推荐!论文分析、文档总结必备神器!
900 1
几款宝藏级AI阅读工具推荐!论文分析、文档总结必备神器!
|
11月前
|
Ubuntu Linux 网络安全
在Linux中,如何禁用root用户直接SSH登录?
在Linux中,如何禁用root用户直接SSH登录?
|
存储 安全 Java
synchronized原理详解(通俗易懂超级好)
当系统检查到锁是重量级锁之后,会把等待想要获得锁的线程进行阻塞,被阻塞的线程不会消耗cpu。但是阻塞或者唤醒一个线程时,都需要操作系统来帮忙,这就需要从用户态转换到内核态,而转换状态是需要消耗很多时间的,有可能比用户执行代码的时间还要长。
synchronized原理详解(通俗易懂超级好)
|
供应链 JavaScript 前端开发
25个常见的python系统设计源码(python+mysql+vue)
25个常见的python系统设计源码(python+mysql+vue)
385 3
|
Web App开发 监控 数据可视化
【JVM实践入门篇】: VisualVM的插件下载
【JVM实践入门篇】: VisualVM的插件下载
840 0
【JVM实践入门篇】: VisualVM的插件下载
|
存储 JSON API
微服务框架 go-zero logx 日志组件剖析
微服务框架 go-zero logx 日志组件剖析
434 0
AI助理
登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问

你好,我是AI助理

可以解答问题、推荐解决方案等