尚硅谷Java大厂面试题第2季,面试必刷,跳槽大厂神器

1.并发和并行有什么区别?
并发就像秒杀,多个线程去访问同一个资源;并行就是各种事情同时去做(比如说我边听音乐边看知乎边聊天)。
2.什么是volatile?
volatile是java虚拟机提供的轻量级的同步机制。
3.volatile有什么特性?
①保证可见性。
②不保证原子性。
③禁止指令重排。
1.JMM(java内存模型)本身是一种抽象的概念,它并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中的各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。
2.硬件速度:硬盘 < 内存 < CPU,CPU和内存之间存在着一片区域叫缓存cache。
3.JMM内存模型的特性:
①可见性:一个线程修改了主物理内存之后,其他线程第一时间会获得通知,这种第一时间通知的机制,就叫做java内存模型的可见性。
1.JMM的三大特性:可见性、原子性、有序性,这三个特性是大多数多线程开发需要遵守的规范。
2.volatile可见性的代码验证说明:
// todo
2.原子性是什么意思?
不可分割,完整性,也即某个线程正在做某个业务时,中间不可以被加塞或者被分割。需要保证整体完整,要么同时成功,要么同时失败。
3.Thread.yield() 方法,使当前线程由执行状态,变成为就绪状态,让出cpu时间,在下一个线程执行时候,此线程有可能被执行,也有可能没有被执行(谁先抢到谁就先执行)。
4.volatile不保证原子性的代码验证说明:
// todo
1.n++操作,实际上被拆分成了3个指令:
①执行getfield拿到原始的n(各个线程从主物理内存中拿到初始值n);
②执行iadd进行加1的操作(各个线程在其工作内存中执行+1的操作);
③执行putfield写,把累加之后的值写回主内存。
2.volatile不保证原子性的理论原因: 各个线程出现了写值丢失的情况(也可以称之为写覆盖)。
1.如何解决原子性?
①加syconized(杀鸡焉用牛刀,不合适);
②使用JUC下带原子(Atomic)的类,例如:AtomicInteger;
1.计算机在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排。会分为以下3种:
编译器优化的重排、指令并行的重排、内存系统的重排。
1.单线程环境里面确保程序最终执行结果和代码顺序执行的结果一致(单线程环境下,不存在指令重排)。
2.处理器在进行重排序时必须要考虑指令之间的依赖性。
3.多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测。
4.禁止指令重排的小总结:
// todo
5.线程安全性获得保证:
①工作内存与主内存同步延迟现象导致的可见性问题如何解决?
答:可以使用synchronized或者volatile关键字解决,它们都可以使一个线程修改后的变量立即对其他线程可见。
②对于指令重排导致的可见性问题和有序性问题,如何解决?
答:可以利用volatile关键字解决,因为volatile的另外一个作用就是禁止重排序优化。
1.在多线程环境下,单例模式会存在安全问题,可以使用DCL模式去解决(Double Check Lock双端检锁机制,在加锁之前和枷锁之后都进行一次判断)。
CAS:compare and swap
1.为什么不用synchronized而用CAS?
答:CAS是乐观锁的一种实现机制,一种无锁机制 在线程等待时间短的情况下,性能更高
2.

Unsafe是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地(native)方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据。Unsafe类存在于sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存,因为Java中CAS操作的执行依赖于Unsafe类的方法。
①注意Unsafe类中的所有方法都是native修饰的,也就是说Unsafe类中的方法都直接调用操作系统底层资源执行相应任务。
②变量valueOffset,表示该变量值在内存中的偏移地址,因为Unsafe就是根据内存偏移地址获取数据的。
③变量value用volatile修饰,保证了多线程之间的内存可见性。
3.CAS是什么?
答:CAS的全称为Compare-And-Swap,它是一条CPU并发原语。
它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的。
1.CAS的缺点:
循环时间长,会给CPU带来很大的开销
只能保证一个共享变量的原子操作
ABA问题
1.ABA问题如何解决?
使用AtomicStampedReference类生成版本号
1.ArrayList是线程不安全的,在多线程环境下,会报错:
java.util.ConcurrentModificationException
解决方法之一:Vector
解决方法之二:Collections.synchronizedList()
解决方法之三:CopyOnWriteArrayList(写时复制读写分离的思想,最推荐)
2.集合并发异常的导致原因:
并发争抢导致,参考花名册签名情况,一个人正在写入,另一个同学过来争抢,导致数据不一致异常,并发修改异常。
HashSet线程不安全的解决方法:
- Collections.synchronizedSet(new HashSet<>())
- CopyOnWriteArraySet<>()(推荐)
解决方法:
- HashTable
- Collections.synchronizedMap(new HashMap<>())
- ConcurrentMap<>()(推荐)
1.公平和非公平锁,是什么?:
公平锁 是指多个线程按照申请锁的顺序来获取锁,类似排队打饭,先来后到。
非公平锁 是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后中请的线程比先中请的线程优先获取锁。在高并发的情况下,有可能会造成优先级反转或者饥饿现象
2.并发包中ReentrantLock的创建可以指定构造函数的boolean类型来得到公平锁或非公平锁,默认是非公平锁。
3.对于ReentrantLock而言,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。
4.对于Synchronized而言,也是一种非公平锁。
指的是同一线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。
也即是说,线程可以进入任何一个它已经拥有的锁所同步着的代码块。
ReentrantLock/synchronized就是一个典型的可重入锁。
可重入锁最大的作用是避免死锁。