synchronized 是Java并发编程中很是重要的角色,这里简单记录对于其原理的学习html
synchronized 具备互斥性,能够保证只有一个线程能够访问同步块编程
synchronized 修饰普通方法,锁为当前实例对象安全
synchronized 修饰静态方法,锁为当前类的Class对象并发
synchronized 修饰同步方法块,锁为代码块括号中填写的对象性能
monitorenter
和monitorexit
两条指令控制同步代码块的访问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 |
加锁与解锁
内容
轻量级锁是经过自旋实现非阻塞同步,属于乐观锁,能够膨胀为重量级锁
Mark Word状态
锁状态 | 记录 | 锁标志位 |
---|---|---|
轻量级锁 | 指向栈中锁记录的指针 | 00 |
加锁与解锁
加锁
解锁
内容
锁升级为重量级锁后,其余试图获取锁的线程均会被阻塞,等待持有锁的线程释放锁后,被唤醒的线程会开始竞争获取锁。
重量级锁是一种互斥锁,其依赖于对象内部的monitor锁实现,在操做系统层面是经过MutexLock实现的。虽然在阻塞时不须要耗费CPU资源,可是线程从阻塞状态唤醒须要操做系统完成状态转换(用户态到内核态),耗时较长。
Mark Word状态
锁状态 | 记录 | 锁标志位 |
---|---|---|
重量级锁 | 指向互斥量(重量级锁)的指针 | 10 |
对比表参考《Java并发编程的艺术》
锁 | 优势 | 缺点 | 适用场景 |
---|---|---|---|
偏向锁 | 加锁和解锁不须要额外的消耗,和执行非同步方法相比仅存在纳秒级的差距 | 若是线程间存在锁竞争,会带来额外的锁撤销的消耗 | 适用于只有一个线程访问同步块的场景 |
轻量级锁 | 非阻塞同步,提升程序响应速度 | 自旋消耗CPU资源 | 追求响应时间,同步方法执行速度较快 |
重量级锁 | 线程阻塞时不须要消耗CPU | 线程阻塞,响应时间缓慢 | 追求吞吐量,同步块执行时间较长 |
若有问题,还请指出