欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java底层原理篇

程序员文章站 2024-03-24 17:45:40
...

被变态的面试官折磨过吗?必须的,这篇就来说说那些面试官常问的所谓原理!同样的,遇到了就会上来更新,并不会立马写完O(∩_∩)O嗯!

一、介绍

  • 所谓原理
    • 原理这个词字我这里理解有下面几层意思:
      1. 代码的执行流程;
      2. 怎么实现的;
    • 看了上面的解释有没有想打我的冲动?如何解释呢?
      1. 执行流程:基本上就会牵扯到一些设计模式之类的问题;
      2. 实现原理:看名字就知道会牵扯到一些数据结构方面的知识;
    • 所以呢,面试的时候如果被问到这类问题,就想想问到的问题具有上面的哪个特征,有哪个,说哪个,两个都有就全说。 (@ο@) 哇~

二、常见原理类问题解析

  1. synchronized底层是怎么实现的?参考
    • 实现方式:
      • synchronized修饰的代码块:底层使用monitorenter和monitorexit指令完成代码块锁的实现;
      • synchronized修饰的方法:底层使用ACC_SYNCHRONIZED标识完成方法锁的实现;
    • 锁的四种状态:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态;这四个状态随着竞争的激烈而逐渐升级;注意:锁可以升级但是不可降级,这种策略是为了提高获得锁和释放锁的效率;
      • 偏向锁:引入偏向锁的目的和引入轻量级锁的目的很像,他们都是为了没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。轻量级锁和偏向锁不同的是:轻量级锁在无竞争的情况下使用 CAS 操作去代替使用互斥量,而偏向锁在无竞争的情况下会把整个同步都消除掉。偏向锁的“偏”就是偏心的偏,它的意思是会偏向于第一个获得它的线程,如果在接下来的执行中,该锁没有被其他线程获取,那么持有偏向锁的线程就不需要进行同步!但是对于锁竞争比较激烈的场合,偏向锁就失效了,因为这样场合极有可能每次申请锁的线程都是不相同的,因此这种场合下不应该使用偏向锁,否则会得不偿失。
      • 轻量级锁:倘若偏向锁失败,虚拟机并不会立即升级为重量级锁,它还会尝试使用一种称为轻量级锁的优化手段(JDK1.6引入)。轻量级锁不是为了代替重量级锁,它的本意是在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗,因为使用轻量级锁时,不需要申请互斥量。另外,轻量级锁的加锁和解锁都用到了CAS操作。注意:轻量级锁能够提升程序同步性能的条件是“对于绝大部分锁,在整个同步周期内都是不存在竞争的”,这是一个经验数据。如果没有竞争,轻量级锁使用 CAS 操作避免了使用互斥量操作的开销。但如果存在锁竞争,除了互斥量开销外,还会额外发生CAS操作,因此在有锁竞争的情况下,轻量级锁比传统的重量级锁更慢!如果锁竞争激烈,那么轻量级将很快膨胀为重量级锁!
      • 自旋锁自适应自旋锁
    • 扩展:
      • monitor,这里指的是监视器锁,这个底层锁依赖于操作系统的 Mutex Lock 来实现的,Java 的线程是映射到操作系统的原生线程之上的。如果要操作一个线程(如:挂起或者唤醒),都需要操作系统帮忙完成,而操作系统实现线程之间的切换时需要从用户态转换到内核态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高,这也是为什么早期的 synchronized 效率低的原因;JDK6中对synchronized关键字进行了相当大的优化。对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。
      • 查看Java的汇编指令:
        javap -c -s -v -l <class-name>.class