Java面试那点事——基础200115

1. 什么是锁消除?什么是锁膨胀

锁消除:

对数据进行逃逸分析。对象实例都是存在于线程共享的堆中的,即便是局部变量的对象,也是存在于堆中,但是局部变量对象的引用是存在于方法栈中的,方法栈是线程私有,线程之间彼此不可见,当对于这样的引用进行加锁和释放锁的时候,其实是没有必要的,因为数据是不会逃逸出去,比如说StringBuffer的append方法,是synchronized修饰的同步方法,虚拟机检测到这类情况不会发生数据逃逸就会在运行的时候消除锁,从而提高性能。

锁膨胀/锁粗化:

原则上需要尽量缩小加锁的范围,把需要同步的代码的范围尽量缩小,这样其他线程可以尽快的获得锁。

但是如果频繁对同一个对象进行加锁和解锁的操作,频繁的同步互斥操作会造成不必要的性能损耗;对于这种情况,需要把加锁提前到对象的第一个操作之前,解锁释放到最后一个对象,例子:StringBuffer对象变成全部局部,此时变成堆的线程共享。


2. 乐观锁有哪几种?主要思想是什么?

乐观锁:偏向锁、轻量级锁、自旋锁

乐观锁的主要思想是:CAS(compare and swap)

CAS是一种思想,并不是一种锁,它是一种原子操作,通过比较传入的值来判断是否更新,一样则更新,不一样则失败。


3. 多线程锁的升级原理是什么?

扫描二维码关注公众号,回复: 8635910 查看本文章

锁的级别从低到高:

无锁—偏向锁—轻量级锁—重量级锁

无锁:不加锁,所有线程都可以对资源进行访问,失败则重试

偏向锁:适用于必须同步但是只有一个线程执行的代码块,虚拟机检测到同步的代码块只有一个线程持续执行,就会在后续加上偏向锁。减少非竞争条件的同步代码,提升性能。

轻量级锁:只有一个线程执行同步代码块的时候会加上偏向锁,当第二个线程加入竞争,偏向锁就会升级会轻量级锁,第二个线程不会阻塞,而是通过自旋等待第一个线程释放锁。第二个线程自旋(也就是CPU空转)可以避免用户态和内核态的转换,提升性能。

重量级锁:当第三个线程加入竞争,轻量级锁就会升级为重量级锁,线程会阻塞等待,直到线程释放锁。


4. 什么是死锁?如何预防死锁?死锁和活锁的区别是什么?

死锁:多个线程因竞争资源而造成的互相等待,没有外力作用则一直等待下去。

死锁条件:

  • 互斥
  • 不剥夺
  • 请求和保持
  • 循环等待

活锁:死锁和活锁的表现都是程序不在运行,但是死锁中所有线程都是出于阻塞状态的,活锁中所有线程都是活的状态,是在运行,不断的try,但是不在继续执行,在做无用功。


【Java 面试那点事】

这里致力于分享 Java 面试路上的各种知识,无论是技术还是经验,你需要的这里都有!

这里可以让你【快速了解 Java 相关知识】,并且【短时间在面试方面有跨越式提升

面试路上,你不孤单!
在这里插入图片描述

发布了148 篇原创文章 · 获赞 835 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/qq_33945246/article/details/103999481