synchronized原理学习笔记

synchronized 是Java并发编程中很是重要的角色,这里简单记录对于其原理的学习html

基础内容

  • synchronized 具备互斥性,能够保证只有一个线程能够访问同步块编程

  • synchronized 修饰普通方法,锁为当前实例对象安全

  • synchronized 修饰静态方法,锁为当前类的Class对象并发

  • synchronized 修饰同步方法块,锁为代码块括号中填写的对象性能

指令实现

  • 同步代码块经过monitorentermonitorexit两条指令控制同步代码块的访问
  • 同步方法经过设置ACC_SYNCHRONIZED标志符控制(也能够经过上述两条指令来实现)

全部Java对象都会有一个monitor,当monitor被持有后,对象就处于锁定状态。当执行到monitorenter指令时,线程会尝试获取对象的monitor,而执行monitorexit后会释放对象的monitor学习

Java SE 1.6为了下降锁的获取、释放形成的性能损耗,增长了偏向锁、轻量级锁。锁的级别由高到低依次为无锁状态、偏向锁、轻量级锁、重量级锁,锁能够升级,但不能够降级优化

偏向锁

内容操作系统

锁由同一线程屡次获取时,会在对象头中记录线程ID,并在以后对同步块的访问时,不须要进行CAS操做来加锁、解锁。线程

Mark Word状态3d

Mark Word记录于对象头,存储对象的hashcode或锁信息

这里补充无锁状态的Mark Word状态

锁状态 hashcode 分代年龄 是否偏向锁 锁标志位
无锁状态 对象的hashcode 对象分代年龄 0 01

偏向锁状态的Mark Word状态

锁状态 Thread ID epoch 分代年龄 是否偏向锁 锁标志位
偏向锁 记录指向的线程id epoch 对象分代年龄 1 01

加锁与解锁

biasedlock

轻量级锁

内容

轻量级锁是经过自旋实现非阻塞同步,属于乐观锁,能够膨胀为重量级锁

Mark Word状态

锁状态 记录 锁标志位
轻量级锁 指向栈中锁记录的指针 00

加锁与解锁

加锁

lightlock

解锁

lightunlock

重量级锁

内容

锁升级为重量级锁后,其余试图获取锁的线程均会被阻塞,等待持有锁的线程释放锁后,被唤醒的线程会开始竞争获取锁。

重量级锁是一种互斥锁,其依赖于对象内部的monitor锁实现,在操做系统层面是经过MutexLock实现的。虽然在阻塞时不须要耗费CPU资源,可是线程从阻塞状态唤醒须要操做系统完成状态转换(用户态到内核态),耗时较长。

Mark Word状态

锁状态 记录 锁标志位
重量级锁 指向互斥量(重量级锁)的指针 10

比较

对比表参考《Java并发编程的艺术》

优势 缺点 适用场景
偏向锁 加锁和解锁不须要额外的消耗,和执行非同步方法相比仅存在纳秒级的差距 若是线程间存在锁竞争,会带来额外的锁撤销的消耗 适用于只有一个线程访问同步块的场景
轻量级锁 非阻塞同步,提升程序响应速度 自旋消耗CPU资源 追求响应时间,同步方法执行速度较快
重量级锁 线程阻塞时不须要消耗CPU 线程阻塞,响应时间缓慢 追求吞吐量,同步块执行时间较长

参考文章

  1. 《Java并发编程的艺术》2.2 synchronized的实现原理与应用
  2. 线程安全(上)--完全搞懂synchronized(从偏向锁到重量级锁)
  3. Java并发编程:Synchronized底层优化(偏向锁、轻量级锁)

若有问题,还请指出

相关文章
相关标签/搜索