【JAVA】java常见面试题——持续更新

一、说一下Synchronized的底层原理

Synchronized的话他底层是基于monitorentermonitorexit两个指令来实现的,因为每一个对象都拥一个monitor监视器,而线程就会通过Synchronized来获取这个监视器,当监视器被获取时,就会进去锁定状态。

当一个线程第一次获取monitor时,monitor的进入数就会从0变成1,当该线程再进获取时,monitor的进入数会再次加1。

但如果其他线程来获取时,发现monitor的进入数不为0,则会出现堵塞状况,直到进入数为0。

但在java6之前,Synchronized是完全依靠操作系统的互斥锁,会进行一个用户态到内核态的切换,所有的同步锁操作都是一个无差别的重量级操作,非常消耗资源。

所以在java6之后,会引入3种不同的monitor实现,为偏向锁,轻量级锁和重量级锁

偏向锁其实就是为了在单线程的情况下,完全不用考虑并发情况,所以不会涉及真正的互斥锁。不必浪费资源。但当有另一个线程来访问时,jvm就会从偏向锁转变为轻量级锁。

轻量级锁的话,虽然已经不是单线程的环境了,但这些线程会根据串行的方式来访问同一个加锁对象。但是还是会消耗重复加锁和解锁的性能开销。当正真发生并发情况时,就会切换为重量级锁。

重量级锁他是完全依靠操作系统互斥锁来实现的锁操作系统的互斥锁会实现线程的切换,从用户态到内核态,所以非常消耗资源。


二、谈谈你对ThreadLocal的理解

ThreadLocal是一个线程的局部变量,用于在线程中保存数据。ThreadLocal保存的数据只属于当前线程。每一个Thread都有自己的一个ThreadLocalMap用于数据存储。通过ThreadLocal将数据存入当前线程的ThreadLocalMap中,其中ThreadLocal作为键,存入的数据为值。

ThreadLocal的价值主要在于线程隔离,在该线程存入的数据也只属于该线程,该数据是其他线程不可见的,起到隔离作用。这样的话,在多线程并发环境下,就可以防止当前线程的值被其他线程所修改。相对于加同步锁,能够有效降低性能损失,提高并发的性能。


三、什么是SpringBoot自动配置

SpirngBoot自动配置就是不需要我们写代码,所有的配置都由SpringBoot自动完成。

我们一般是通过@EnableAutoConfiguration这个注解来开启自动配置的,通过对spring-boot-auto-configure包下的spring.factories这个文件进行扫描,这个文件中包含了可以自动装配的类,当满足@Condition注解指定的条件时,便在依赖的支持下进行实例化注册到Spring容器中。

SpringBoot最大特点就是他去除了各种xml配置文件改为application.yml进行统一的配置,并且按照阶梯的模式,简单明了,要使用的对象,则采取注解模式注入,省去大量代码。


四、在使用ThreadLocal时存在什么风险,有什么注意事项

可能发生内存泄漏因为ThreadLocalMap使用ThreadLocal的弱引用为key,如果ThreadLocal没有一个强引用来引用他,那么在下一次GC时势必会回收这个ThreadLocal,从而导致在ThreadLocalMap中存储的一个key为null的值,如果当前线程迟迟不结束的话,那么这个value就会一直存在一条强引用链,从而导致value无法回收,造成内存泄漏。

解决方案:在每次使用完ThreadLocal后都调用他的remove()方法,清除数据。


注:本篇文章都是我自己的理解,可能用词和语句不够严谨,如有错误请评论指正,谢谢!(持续更新中......)

你可能感兴趣的:(jvm,java,面试题,秋招)