目录
Synchronized的表现形式
普通同步方法
- 普通同步方法使用
synchronized
关键字修饰,锁对象是当前实例对象(即方法所属对象的实例)。
public synchronized void method() {
// 锁对象是当前实例对象
}
静态同步方法
- 静态同步方法使用
synchronized
关键字修饰,锁对象是当前类的Class
对象。
public static synchronized void staticMethod() {
// 锁对象是当前类的 Class 对象
}
同步方法块
- 同步方法块可以指定任意对象作为锁对象。
public void method() {
synchronized (lockObject) {
// 锁对象是 synchronized 括号里配置的对象 lockObject
}
}
Java对象头
锁的原理
JVM
基于
进
入和退出
Monitor
对象来实现
方法同步和代
码块
同步,但两者的
实现细节
不一
样
。代
码块
同步是使用
monitorenter和monitorexit
指令
实现
的,而方法同步是使用另外一种方式
实现
的,
细节
在
JVM
规
范里并没有详细说明。但是,方法的同步同
样
可以使用
这
两个指令来
实现
。
monitorenter指令是在
编译
后插入到同步代
码块
的开始位置,而
monitorexit
是插入到方法
结
束
处
和异常
处
,
JVM
要保
证
每个
monitorenter
必
须
有
对应
的
monitorexit
与之配
对
。任何
对
象都有
一个
monitor
与之关
联
,当且一个
monitor
被持有后,它将
处
于
锁
定状
态
。
线
程
执
行到
monitorenter
指令
时
,将会
尝试获
取
对
象所
对应
的
monitor
的所有
权
,即
尝试获
得
对
象的
锁
。
总结来讲就是两点
- 标记锁的开始和结束
- 在对象头中做标记
锁的升级
偏向锁
当前线程加锁,先不释放锁,等到有线程来请求锁,并且当前线程已经执行完毕,才会释放锁。
轻量级锁
当锁被其他线程持有,该线程会一直通过自旋的方式来竞争锁。
重量级锁
当轻量级锁解锁时,存在锁的竞争,则会升级成为重量级锁,竞争失败的线程会进入堵塞队列。