文章目录

  • 前言
  • 一、synchronized是什么?
  • 二、具体内容
  • 1.加锁原理
  • 2.锁升级
  • 总结



前言

synchronized和Lock是面试官常问的问题,本文会讲述synchronized的加锁原理以及锁升级内容。


一、synchronized是什么?

synchronized关键字就是同步块,可以加在代码块上,也可以加在方法上,使被标注的部分只能允许单线程访问,执行完后自动释放锁。
synchronized加在静态方法和静态代码块上是锁的类,在实例方法和代码块上是锁方法。

二、具体内容

1.加锁原理

synchronized加在方法上和加在代码块上的原理是不一样的;

方法的同步是隐式的,synchronized使用的是ACC_SYNCHRONIZED标志,该标志存储在常量池中,当线程访问方法时,会查看有没有该标志,有的话会尝试获取监听器锁,然后执行方法,方法执行完后释放锁。方法执行时有其他线程请求执行方法,会因为无法获得监听器锁而被阻断住。
如果方法执行期间出现没有被处理掉的异常,会在异常发出去之前释放锁。

代码块的同步用monitorentermonitorexit指令来实现。

monitorenter可以理解为加锁,monitorexit可理解为释放锁。每个对象有一个计数器,未被锁定计数为0,执行monitorenter后,计数器自增加1,同一线程再次获取该对象锁时,继续自增。执行monitorexit后,计数器自减,为0时释放锁,其他线程可以获得锁。

2.锁升级

无锁:未加任何锁的代码。

偏向锁:未加锁的代码默认状态是无锁的,当加了synchronized后,获得偏向锁(一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价)。

轻量级锁:当锁是偏向锁时,如果有其它线程想访问该代码,锁就会升级成轻量级锁(也被称为自旋锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能)。

重量级锁:轻量级锁长期自旋是非常消耗资源的,一个县城持有锁,其它线程就只能等待,空耗CPU,但有一个计数器记录自旋次数,当次数达到10次的时候,锁升级为重量级锁,此时所有等待锁的线程都会进入等待状态。

锁升级:无锁 -> 偏向锁 -> 轻量级锁(自旋锁) -> 重量级锁


总结

synchronized是一个非常重要的知识点,用处非常广范,必须掌握;