java基础面试原文略作修改
1 线程和进程
进程是程序的一次执行,是操作系统调度和分配资源的基本单位,因为进程的创建和销毁占用大量的时间和空间,进程的数量不能太多,
线程是更加轻量级的能独立运行的基本单位,他是进程的实体,可以减少程序运行的并发执行时间和空间,使得操作系统有更好的并发性
2 synchronized原理
synchronized是java内置的隐式锁,使用synchronized后 会在编译后的代码块前后添加monitorenter和monitorexit字节码指令
他主要依赖操作系统的底层互斥锁实现,他的主要作用就是实现原子操作和解决共享变量的内存可见性问题
执行monitorenter指令时会尝试获取对象锁,锁的计数器+1,如果已经有线程获取了对象锁,则当前线程进入等待队列
执行monitorexit指令时 锁的计数器-1,当计数器为0时,锁释放,其他线程继续竞争锁
从内存语义上说,加锁会清除工作线程中的共享变量从主内存读取,
释放锁的过程是将工作内存中的共享变量写回主内存
3 锁的优化机制
优化包括 自旋锁,自适应锁,锁消除 ,锁粗化,偏向锁,轻量级锁
自旋锁: 由于大部分时候,锁被占用的时间很短,共享变量的锁定时间也很短,所以没必要挂起线程,
可以尝试让线程自旋获取锁,防止线程挂起
自适应锁: 自旋时间不固定 由上一个锁上的线程自旋时间决定.
锁消除: 代码不存在竞争的场景进行锁消除
锁粗化: 锁的粗化是指很多操作对同一个对象加锁,将锁的同步范围扩大.
偏向锁: 线程进入同步代码获取锁之后,会在对象头信息中记录线程id,下次进入代码块就不需要获取锁
,如果没有后续线程获取锁,则不需要加锁,如果有则放弃偏向锁 升级为轻量级锁
轻量级锁: jvm对象的对象头信息中包含一些锁的标志位,代码进入同步块的时候,线程会使用cas的方式获取锁
如果获得锁 则会把对象头信息中的状态标记为轻量级锁,如果标记失败则尝试自选获取锁
重量级锁:除了当前用有锁的线程 ,其他的全部阻塞
4 java线程状态
1) 新建 创建未运行
2) 运行状态
3) 限期等待
4) 无限期等待
5) 阻塞
6) 结束
5 ReenTrantLock和synchronized的区别
reentrantlock可以进行等待唤醒可以不阻塞线程
6 reentrantlock的实现原理
基于aqs实现,aqs内部维护一个state状态位,尝试加锁的时候通过cas修改值,如果修改状态成功,并把当前线程id赋值,则代表加锁成功,
获取锁失败则进入等待队列,释放锁的时候会唤醒阻塞队列中的线程,并且将线程id置空,state状态为置为0
7 cas原理
cas主要通过处理器的指令保证操作的原子性,只有当前线程值和主内存值一致时才会更新
缺点 比较更新不成功则进入自旋会占用cpu性能
8 线程池原理
分3个步骤进行:
1.提交任务 判断核心线程池是否已满,未满创建一个线程执行任务,
2 否则判断缓存任务的队列是否已满,未满则放入队列
3 已满则判断是否达到最大线程数,未满创建一个新的线程执行任务,否则执行任务拒绝策略
4 创建后的work线程都是从队列中获取任务执行
5 参考详细代码分析 https://blog.csdn.net/qq_32651225/article/details/89716027
9 同步阻塞和异步非阻塞
同步阻塞举例 火车站售票排队按顺序买票,期间排队的人是不能随意离开干其他事情的,这种情况就是阻塞住了
异步非阻塞举例 银行排队叫号 办理业务首先取号,然后等待通知,在这期间人是可以自由活动处理其他事情的不需要在窗口排队,这就是非阻塞