文章目录
- 前言
- 一、synchronized是什么?
- 二、具体内容
- 1.加锁原理
- 2.锁升级
- 总结
前言
synchronized和Lock是面试官常问的问题,本文会讲述synchronized的加锁原理以及锁升级内容。
一、synchronized是什么?
synchronized关键字就是同步块,可以加在代码块上,也可以加在方法上,使被标注的部分只能允许单线程访问,执行完后自动释放锁。synchronized加在静态方法和静态代码块上是锁的类,在实例方法和代码块上是锁方法。
二、具体内容
1.加锁原理
synchronized加在方法上和加在代码块上的原理是不一样的;
方法的同步是隐式的,synchronized使用的是ACC_SYNCHRONIZED标志,该标志存储在常量池中,当线程访问方法时,会查看有没有该标志,有的话会尝试获取监听器锁,然后执行方法,方法执行完后释放锁。方法执行时有其他线程请求执行方法,会因为无法获得监听器锁而被阻断住。如果方法执行期间出现没有被处理掉的异常,会在异常发出去之前释放锁。
代码块的同步用monitorenter和monitorexit指令来实现。
monitorenter可以理解为加锁,monitorexit可理解为释放锁。每个对象有一个计数器,未被锁定计数为0,执行monitorenter后,计数器自增加1,同一线程再次获取该对象锁时,继续自增。执行monitorexit后,计数器自减,为0时释放锁,其他线程可以获得锁。
2.锁升级
无锁:未加任何锁的代码。
偏向锁:未加锁的代码默认状态是无锁的,当加了synchronized后,获得偏向锁(一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价)。
轻量级锁:当锁是偏向锁时,如果有其它线程想访问该代码,锁就会升级成轻量级锁(也被称为自旋锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能)。
重量级锁:轻量级锁长期自旋是非常消耗资源的,一个县城持有锁,其它线程就只能等待,空耗CPU,但有一个计数器记录自旋次数,当次数达到10次的时候,锁升级为重量级锁,此时所有等待锁的线程都会进入等待状态。
锁升级:无锁 -> 偏向锁 -> 轻量级锁(自旋锁) -> 重量级锁
总结
synchronized是一个非常重要的知识点,用处非常广范,必须掌握;