这次电面是本人第一次求职面试,面试过程中也有一些问题答不上来或需要提示才能答出,但整体答题较为流畅,运气尚佳通过了此次面试。感谢前辈们分享的面经,也将此次面试经历记录并分享。虽然答案只是个人粗浅的理解,希望能对正在求职的小伙伴有帮助,也欢迎各位指出我的不足~
操作系统基础
Q1:简述进程线程
A:进程是系统分配资源的独立单位,线程是系统调度的基本单位
追问: 线程是否有独立内存?A:有,线程共享进程的内存空间,通过互斥锁独立访问
Q2:了解乐观锁悲观锁么
乐观锁
该机制假设每次拿数据的时候都认为别人不会修改,因此不加锁,但在更新时会去判断在此期间别人是否有更新这个数据,使用版本号机制和CAS算法实现。适用于读操作多的应用,提高吞吐量。
CAS算法(并未提问该算法,仅作为个人补充)
C(compare) A(and) S(swap). 无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization。
该算法涉及到三个操作数
- 需要读写的内存值 V
- 进行比较的值 A
- 拟写入的新值 B
算法主要思想如下:“我认为V的值应该为A,如果是,那么将V的值更新为B,否则不修改并告诉V的值实际为多少”。当且仅当 V 的值等于 A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作。在多个线程尝试修改同一内存时,只有一个线程可以修改成功,失败的线程不会被挂起,可以再次尝试
悲观锁
该机制假设每次拿到数据的时都认为别人会修改,所以每次拿到数据都会加锁。传统关系数据中的读锁写锁机就是这种机制
Java基础
Q3:java里的同步实现方法
该部分并未完整答出,给出的答案是整理自网络,若有错误请指正。
synchronized(悲观锁)
该关键字调用java对象的内置锁,进而保护整个方法/对象
//usage1
public synchronized void save(){}
//usage2
synchronized(object){
}
volatile
a.volatile关键字为域变量的访问提供了一种免锁机制,
b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,
c.因此每次使用该域就要重新计算,而不是使用寄存器中的值
d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量
//修饰需要同步的变量,该变量不能用final修饰
private volatile int account;
ReentrantLock(悲观锁)
Java.util.concurrent
包中的ReentrantLock类是可重入,互斥,实现了Lock接口的锁
ThreadLocal
使用该类管理变量,则每个使用该变量的线程都获得该变量的副本,副本直接互相独立,可在线程中随意修改互不影响。
算法&数据结构
数据结构考题较为基础,因为是电面没有写码而是口述思路。后续补充相应代码
Q4:非递归的先序遍历2叉树
先序:根,左子节点,右子节点
维护一个栈,将根结点压入栈。
进入循环,判断栈是否为空,非空则输出栈顶元素并出栈
判断该节点是否有子节点,按右子节点,左子节点顺序入栈。
循环之
Q5:树的层次遍历
维护一个队列,将根结点入队
进入循环,判断队是否为空,非空则输出队首元素并出队
判断该节点是否有子节点,若有,则依次(左,右)入队
循环之
Q6:栈实现队列的功能
维护两个栈,S1负责接收入队元素,S2负责完成出队操作
push:直接压入S1
poll: 判断S2是否为空,非空则将S2栈顶元素出栈作为输出,否则将S1中元素依次出栈压入S2,直到S1中只含一个元素,将其出栈作为输出
Q7:o(1)复杂度算栈内最大值
该题只要求O1时间复杂度,空间复杂度方面没有限制
同样维护两个栈,S作为主栈存储元素,MaxS记录当前S中最大值
Push:判断S是否为空,若为空,则将该元素X入栈S和MaxS,否则比较X与MaxS.head(),若X>MaxS.head(),则将X压入两个栈,否则X入栈S,MaxS再次压入其栈顶元素
Pop: S弹出元素后MaxS也出栈栈顶元素
Max(S): 即MaxS.head()
Q8&9:简述快排思想,递归的缺点
基础题,不赘述
网友评论