[TOC]
<br/>
> ### `Synchronized`同步类型
* 对于普通同步方法,锁是当前实例对象。
* 对于静态同步方法,锁是当前类的`Class`对象。
* 对于同步方法块,锁是`Synchonized`括号里配置的对象。
<br/>
> ### `Synchronized`底层实现
* `JVM`基于进入和退出`Monitor`对象来实现方法同步和代码块同步,但两者的实现细节不一样。代码块同步是使用`monitorenter`和`monitorexit`指令实现的。 `monitorenter`指令是在编译后插入到同步代码块的开始位置,而`monitorexit`是插入到方法结束处和异常处,任何对象都有一个`monitor`与之关联,当且一个`monitor`被持有后,它将处于锁定状态。线程执行到`monitorenter`指令时,将会尝试获取对象所对应的`monitor`的所有权,即尝试获得对象的锁。
* `synchronized`用的锁是存在`Java`对象头里的`Mark Word`
<br/>
> ### `Java`对象头
* 如果对象是数组类型,则虚拟机用3个字宽(`Word`)存储对象头,如果对象是非数组类型,则用2字宽存储对象头。数组对象相对于普通对象多了一个字宽记录数组长度。
![](https://i.loli.net/2019/03/10/5c84ba6634f78.png)
<br/>
> ### `Java1.6`之后锁的升级
* **偏向锁**,偏向锁使用了一种等到竞争出现才释放锁的机制,所以当其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁。偏向锁的锁记录存储在对象头中。
![](https://i.loli.net/2019/03/10/5c84d33dc9a79.png)
* **轻量级锁**,线程在执行同步块之前,JVM会先在当前线程的栈桢中创建用于存储锁记录的空间,并将对象头中的`Mark Word`复制到锁记录中,官方称为`Displaced Mark Word`。然后线程尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。
![](https://i.loli.net/2019/03/10/5c84d357441ed.png)
* 偏向锁、轻量级锁、重量级锁对比
![](https://i.loli.net/2019/03/10/5c84cfda13ae7.png)
- asD
- Java
- Java基础
- Java编译器
- 反射
- collection
- IO
- JDK
- HashMap
- ConcurrentHashMap
- LinkedHashMap
- TreeMap
- 阻塞队列
- java语法
- String.format()
- JVM
- JVM内存、对象、类
- JVM GC
- JVM监控
- 多线程
- 基础概念
- volatile
- synchronized
- wait_notify
- join
- lock
- ThreadLocal
- AQS
- 线程池
- Spring
- IOC
- 特性介绍
- getBean()
- creatBean()
- createBeanInstance()
- populateBean()
- AOP
- 基本概念
- Spring处理请求的过程
- 注解
- 微服务
- 服务注册与发现
- etcd
- zk
- 大数据
- Java_spark
- 基础知识
- Thrift
- hdfs
- 计算机网络
- OSI七层模型
- HTTP
- SSL
- 数据库
- Redis
- mysql
- mybatis
- sql
- 容器
- docker
- k8s
- nginx
- tomcat
- 数据结构/算法
- 排序算法
- 快排
- 插入排序
- 归并排序
- 堆排序
- 计算时间复杂度
- leetcode
- LRU缓存
- B/B+ 树
- 跳跃表
- 设计模式
- 单例模式
- 装饰者模式
- 工厂模式
- 运维
- git
- 前端
- thymeleaf
- 其他
- 代码规范
- work_project
- Interview