前言
synchronized 在jdk6之前是很笨重的,不同线程的加锁解锁会引起操作系统内核态的切换,十分消耗性能,不过jdk6之后它正在向着智能方向发展——它能根据当前线程运行环境来自动切换不同的锁
具体的实现过程我觉得如果不是有专门的开发需求,没必要了解的很透彻,它对业务都是透明的,可以简单了解实现的思想
简述
首先说synchronized 将一个对象当做锁,对象可以是普通类的实例对象或者是类的class对象,锁的升级过程是:
- 无锁状态的前提下有一个线程来请求synchronized锁住的资源,此时该线程获得的锁是偏向锁,即那个被当做锁的对象就是偏向锁,偏向锁的特点是下一次该线程获取锁的成本是0,我们要知道通常线程获取锁释放锁是需要成本的(可以理解成通常的synchronized加锁会通过CAS操作来变更信号量),但偏向锁通过判断当前锁上的线程是将要加锁的线程且当前锁是偏向锁这两点就可以获取到并发资源
- 当有另一个线程来抢占锁时就会发生偏向锁向轻量级锁的升级,轻量级锁是一个自旋锁,先不阻塞线程,自旋一段时间(一定次数),看能否获取到锁。适用于锁资源执行较快立马就会释放锁的情况下。
还有一种适应性自旋锁,自旋次数不是一成不变的而是根据前几次执行的情况来动态改变当前自旋次数。在单核系统下自旋锁是无效的,因为单核系统不存在真正的并行,只是时间片的轮转,同一时刻只能有一个线程执行,自旋的目的是等待其他线程,而这里的等待就没有必要了,所以单核系统也禁用了自旋锁 - 当自旋到一定时间(次数)后就会升级为重量级锁,重量级锁使除了拥有锁的线程以外的线程都阻塞,防止CPU空转。