Synchronized的原理

在多线程并发编程中Synchronized一直是元老级角色,很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,Java SE1.6中为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁,以及锁的存储结构和升级过程。

1、阻塞代价
java的线程是映射到操作系统原生线程之上的,如果要阻塞或唤醒一个线程就需要操作系统介入,需要在用户态与核心态之间切换,这种切换会消耗大量的系统资源,因为用户态与内核态都有各自专用的内存空间,专用的寄存器等,用户态切换至内核态需要传递给许多变量、参数给内核,内核也需要保护好用户态在切换时的一些寄存器值、变量等,以便内核态调用结束后切换回用户态继续工作。如果线程状态切换是一个高频操作时,这将会消耗很多CPU处理时间;如果对于那些需要同步的简单的代码块,获取锁挂起操作消耗的时间比用户代码执行的时间还要长,这种同步策略显然非常糟糕的。synchronized会导致争用不到锁的线程进入阻塞状态,所以说它是java语言中一个重量级的同步操纵,被称为重量级锁,为了缓解上述性能问题,JVM从1.5开始,引入了轻量锁与偏向锁,默认启用了自旋锁,他们都属于乐观锁。

2、整个synchronized锁流程如下:
a.检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁
b.如果不是,则使用CAS将当前线程的ID替换Mard Word,如果成功则表示当前线程获得偏向锁,置偏向标志位1
c.如果失败,则说明发生竞争,撤销偏向锁,进而升级为轻量级锁。
d.当前线程使用CAS将对象头的Mark Word替换为锁记录指针,如果成功,当前线程获得锁
e.如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。
f.如果自旋成功则依然处于轻量级状态。
g.如果自旋失败,则升级为重量级锁。

你可能感兴趣的:(java)