一句话解释:
JVM会自动通过monitor来加锁和解锁,保证了同时只有一个线程能够执行指定的代码,从而保证了线程安全,同时具有可重入和不可中断的性质。
用法:
synchronize两种用法:
对象锁和类锁
对象锁分为代码块形式和方法锁形式
#方法锁
public synchronize void method(){
...
}
#代码块锁
public void method(){
synchronize(this){
...
}
}
类锁,效果是全局锁定,因为jvm中只有一个这个类class,但可以有多个实例(new对象)
#形式1, 加在static方法上
public static synchronize void method(){
...
}
#形式2, 使用.class 形式
public void method(){
synchronize(object.class){
...
}
}
同步方法7中情况:
- 两个线程访问的是一个对象的同一个同步方法 顺序执行,串行 正常运作,会同步
- 两个线程访问的是两个实例的同一个方法 相互不影响
- 两个线程访问的是synchronized的静态方法 相互影响串行,类锁情况
- 同时访问同步方法与非同步方法 不相互影响 非同步方法不受影响
- 访问同一个对象的不同的普通同步方法 拿到的锁时同一把锁,同一个实例,所以受到影响,不能同时运行
- 同时访问静态synchronized和非静态synchronized方法 背后的锁对象不是同一个,所以可以并行执行
- 方法抛出异常后,会释放锁 正确,抛出异常后,会自动释放锁
性质:
可重入性。好处:避免死锁,提高封装性;粒度,是线程而不是调用
不可中断
原理:
加锁和解锁的原理:现象、时机、深入JVM字节码
可重入行原理:加锁次数计数器
- JVM负责跟踪对象被加锁次数(moniterenter monitorexit)
- 线程第一次给对象加锁的时候,计数器+1,每当这个相同的线程在此对象上再次获得锁,计数器会递增。
- 每次任务离开,计数器递减,当计数器为0时,锁完全释放
保证可行性原理:内存模型。线程的有本地内存,线程间通过逐内存进行通信
缺陷:
效率低
- 锁的释放时机情况少
- 试图获得锁时,不能设置超时时间
- 不能中断一个正在试图获取锁的线程
不够灵活
- 加解锁时机单一
- 每个锁仅有单一的条件,可能不够
不知道是否已经成功获取到锁