本文已参与「新人创作礼」活动,一起开启掘金创作之路。
基本介绍
synchronized优化主要是在四个方面:重量级锁,轻量级锁,自旋锁,偏向锁,接下来的内容都会讲解这些锁。
关于锁的生动形象例子
故事角色 老王 - JVM/操作系统 小南 - 线程 小女 - 线程 房间 - 对象 房间门上 - 防盗锁 - Monitor 房间门上 - 小南书包 - 轻量级锁 房间门上 - 刻上小南大名 - 偏向锁 批量重刻名 - 一个类的偏向锁撤销到达 20 阈值 不能刻名字 - 批量撤销该类对象的偏向锁,设置该类不可偏向
小南要使用房间保证计算不被其它人干扰(原子性),最初,他用的是防盗锁,当上下文切换时,锁住门。这样, 即使他离开了,别人也进不了门,他的工作就是安全的。
但是,很多情况下没人跟他来竞争房间的使用权。小女是要用房间,但使用的时间上是错开的,小南白天用,小女 晚上用。每次上锁太麻烦了,有没有更简单的办法呢?
小南和小女商量了一下,约定不锁门了,而是谁用房间,谁把自己的书包挂在门口,但他们的书包样式都一样,因 此每次进门前得翻翻书包,看课本是谁的,如果是自己的,那么就可以进门,这样省的上锁解锁了。万一书包不是 自己的,那么就在门外等,并通知对方下次用锁门的方式。
后来,小女回老家了,很长一段时间都不会用这个房间。小南每次还是挂书包,翻书包,虽然比锁门省事了,但仍 然觉得麻烦。
于是,小南干脆在门上刻上了自己的名字:【小南专属房间,其它人勿用】,下次来用房间时,只要名字还在,那 么说明没人打扰,还是可以安全地使用房间。如果这期间有其它人要用这个房间,那么由使用者将小南刻的名字擦 掉,升级为挂书包的方式。
同学们都放假回老家了,小南就膨胀了,在 20 个房间刻上了自己的名字,想进哪个进哪个。后来他自己放假回老 家了,这时小女回来了(她也要用这些房间),结果就是得一个个地擦掉小南刻的名字,升级为挂书包的方式。老 王觉得这成本有点高,提出了一种批量重刻名的方法,他让小女不用挂书包了,可以直接在门上刻上自己的名字 后来,刻名的现象越来越频繁,老王受不了了:算了,这些房间都不能刻名了,只能挂书包
这个故事就是类比与上述几种锁,各位可以在理解不清楚时 回来类比看看。 重点:轻量级锁
轻量级锁如果开始竞争 则变为重量级锁
轻量级锁如果长时间是自己一个线程 则变为偏向锁
轻量级锁 在变为重量级锁的过程中 竞争的线程并不会直接进入Monitor的阻塞列表 而是会先变为自旋锁 看是否有机会直接获取锁
应用场景
如果一个对象虽然有多个线程访问,但是多线程访问的时间是错开的(也就是没有竞争),那么可以用轻量级锁来优化,有同学可以会有疑惑既然都没有竞争了为什么要用多线程,因为只是大部分时间是没有竞争 还是会出现有竞争的情况 此时就要把锁变为重量级锁
Thread-0线程
假设有两个方法同步块,利用一个对象加锁
static final Object obj = new Object();
public static void method1(){
synchronized(obj){
// 同步块A
method2();
}
}
public static void method2(){
synchronized(obj){
// 同步块B
}
}