一、概述
synchronizd是Java中一个重要的关键字,也是我们平时开发时常用的同步方法。他可以作用于同步实例方法、类方法(静态方法)和代码块。synchronizd是重量级的锁,可以保证共享变量的可见性、有序性和原子性。同时synchronizd也是一个非公平锁,可以重入。
二、底层实现
synchronizd的依赖于底层 依赖于操作系统的mutex互斥原语,通过Java对象的对象头的Mark Word和moniter实现的,Java的对象头里边的信息非常重要是jvm实现很多其他功能的重要依赖,信息如下:
当锁为重量级锁时,通过Monitor实现的;当锁为偏向锁、轻量级锁时是通过java的对象头实现的
三、锁膨胀的过程
如下所示,锁主要存在四种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态,他们随着竞争的情况逐渐升级。
(1)、对象最开始是无锁状态的001;
(2)、偏向锁,顾明思义,他会偏向于第一个访问的线程。第一个使用该对象的线程对该对象加synchronized操作后便是是偏向锁101,默认以后只有这个线程使用该对象,若果偏向锁开关没开的话这时候加锁的便是轻量级锁00了;这样设计偏向锁的的好处是:如果自始至终使用该对象的线程真的只这有一个的话,很明显几乎就没有什么额外的开销,性能极高,毕竟需要加锁的对象是少数,适合大多数的对象的情况。偏向锁是不可逆的,一旦某个线程加上了偏向锁就不会回到无锁状态了。
(3)、当再来第二个线程通过CAS加锁,这时候如果能加锁成功,是轻度的竞争,对象就变为轻量级锁00。因为此时是新来的线程,对象头中存入的是之前的偏向线程,只要新来的线程和之前的偏向线程不是同一个线程就会变为轻量级锁,就会消除对象上的偏向锁;
(4)、如果步骤三中的的对象正在拿着轻量级锁,此时再来新的线程竞争的话,如果能够通过CAS获取到锁便还好还是轻量级锁;如果竞争拿不到锁,便通过自旋或者自适应自旋来获取,如果能成功便还是轻量级锁;如果自旋不成功,便会升级为重量级锁。