并发编程面试题大赏

基础问题

  1. 程序、进程 和线程

程序启动了就是一个进程
进程是系统资源分配和调度的独立单位
线程是进程的一个实体,是cpu分配和调度的基本单位,一个进程有多个线程,线程组之间共享进程的数据。
进程切换开销大,线程切换开销小

  1. 并发编程的三要素

可见性、原子性、有序性

  1. 并行和并发

并行:单位时间内,多个处理器或多核处理器同时处理多个任务
并发:一个时间段内,多个任务在同一个CPU核上,按细分的时间片交替执行

  1. 什么是多线程?多线程的优势和劣势

多个不同线程执行不同任务
优势:充分利用CPU,减少阻塞时间,提高系统吞吐率
劣势:带来线程不安全问题:脏读、幻读、数据修改丢失;上下文切换、内存泄露等问题;线程多,占用内存也多

  1. 什么是上下文切换

一个线程切换到另一个线程。需要保存上一个线程的执行信息,以便下次切换回来

  1. 线程的实现方式

1.继承Thread 2.实现Runnable 3.实现Callable 4.线程池

  1. 守护线程和用户线程的区别

用户线程还在执行,jvm就不会退出。守护线程随着jvm的退出而退出。
使用场景:后台任务可作为守护线程,需要jvm退出时跟着一起退出
典例:垃圾回收线程

  1. . windows和Linux如何查找哪个线程CPU利用率最高

linux:
1)ps -cf|grep java 找到CPU耗用最高的进程pid
2)top -H -p pid
windows看任务管理器

  1. 如何获取线程dump文件,如何在java中获取线程堆栈

js -pf|grep java获取进程id
jmap命令获取dump信息
jstack分析dump文件

  1. java如何保证多线程运行安全?

synchronized关键字、Lock锁实现、分布式锁实现

  1. 同步方法和同步块哪个更好?

同步块。同步块以外的代码可以异步执行

  1. 线程优先级

操作系统中线程分优先等级。优先级高的线程获得CPU资源概率大。数字越大,优先级越高。优先级具有继承性

  1. 线程运行时发生异常会怎么样

线程结束

  1. java线程数过多会怎么样

占用CPU内存多
大量线程竞争CPU资源,开销大
稳定性下降

  1. 线程调度策略

抢占式调度模型。优先级别高的线程先占用CPU

  1. 线程调度算法

优先级高的线程先运行,以下情况终止运行
调用wait或者yield
调用sleep方法
IO操作阻塞
时间片用完

  1. 线程调度器和时间分片

线程调度器:操作系统服务,负责给Runnable状态的线程分配CPU
时间分片:过程,把CPU分配给Runnable状态的线程的过程

线程创建

  1. 如何创建线程

1.继承Thread 2.实现Runnable 3.实现Callable 4.线程池

  1. 什么是Callable和Future

Callable实现线程,创建线程的接口。实现Callable接口的线程执行会有返回值,返回值由通过Future接口获取。

  1. Callable和Runnable区别

Callable 实现的线程,允许抛出异常,获取异常信息。有返回值。配合Future和FutureTask可以获取异步任务执行的结果
Runnable实现的线程没有返回值,只能运行时异常,无法捕获异常

  1. 线程的start和run方法的区别

run方法是线程体。线程里的方法。线程执行时运行的代码
通过start去启动线程。
run方法可重复调用,start只能调用一次
start无需等run方法里的代码执行完毕,可以去执行其他代码

  1. 什么是futureTask

表示异步运算的任务。FutureTask实现了Runnable接口,构造方法参数有Callable类型的参数,从而可以获取这个异步运算任务的执行结果,判断是否完成,取消任务等

线程状态

  1. 线程的几个状态

创建、就绪、执行、阻塞、消亡
创建线程,调用start方法,线程进入就绪状态;线程时间片用完也会进入就绪状态
线程拥有CPU控制权,开始执行
阻塞分几种:同步阻塞、等待阻塞和其他阻塞
同步阻塞:其他线程抢占CPU失败,CPU已被其他线程占用
等待阻塞:线程调用wait方法,放入等待队列,进入阻塞状态,被唤醒后要抢占CPU
其他阻塞:线程调用join方法,sleep方法,进入阻塞状态。等其他线程执行完,sleep时间到,进入就绪状态

线程通信问题

  1. sleep()和wait()的区别

sleep是Thread的方法,wait是Object的方法
sleep抱着资源睡觉,时间到了之后就会自动苏醒。wait需要用notify方法唤醒
用途:sleep用于暂停线程执行;wait被用于线程通信
sleep不释放锁,wait是否锁

  1. 为什么多线程需要用while不用if

因为if只会执行一次。会导致虚假唤醒
什么是虚假唤醒?只有部分线程唤醒有用,其他线程唤醒没用

  1. 为什么wait、notify要被定义在Object里面

java中任何对象都能作锁。方法用户等待或唤醒对象的锁或者唤醒线程

  1. 为什么wait、notify方法只能在同步方法或块里使用?

因为这两个方法是Object类的。这些方法需要获得对象的锁才能使用,因此只能通过同步去实现

  1. notify和notifyAll的区别

notify唤醒一个线程
notifyAll中唤醒所有线程
HotSpot虚拟机中notify唤醒第一个等待 的线程,notifyAll先唤醒最后一个等待的线程

  1. 为什么Thread的sleep、join、yield方法是静态的

如果不是静态的,实例方法可以在一个线程内强制使另一个线程sleep,yield

  1. 代码实现:两个线程,t1线程打印5次,t2线程打印10次。接着t1线程打印5次,t2线程打印10次。这样循环10次

封装打印5次和10次的方法
1)t1线程for循环10次,调用print5方法。每次执行完print5,就调用notify,再调用wait阻塞自己
t2线程一开始先调用wait阻塞自己。for循环10次,调用print10方法,每次执行完就调用notify,然后再调用wait阻塞自己。
注意!t1for循环完,要再调用一个notify,否则,最后一次打印没人唤醒,程序无法停止
2)用LockSupport,t1线程先打印完unpark t2线程,再park自己
t2线程先park自己,等待t1unpark t2,打印之后,再park自己

  1. 代码实现:生产者消费者,t1线程生产一个,t2线程消费一个。来10轮

synchronized方法
ReentrantLock,condition方法

关键字

synchronized

  1. 什么是synchronized

jvm同步机制,java内部监视锁。底层:对象头+Monitor对象。指令monitorEnter、monitorExit;每个对象对应一个monitor对象,monitor包含两个队列:waitSet、entryList,owner变量,计数器
抢占cpu的线程放到entryList队列,占用cpu的线程,owner置为当前线程,计数器加1 ;
线程释放资源,owner置为null,计数器-1
线程被阻塞挂起,放入到waitSet队列。

  1. synchronized使用

同步块、同步方法

  1. synchronized锁的对象是什么

类、对象、方法

volatile

  1. 什么是volatile

java轻量级同步机制。保证共享变量的可见性

  1. volatile特性

可见性、有序性

  1. volatile底层

底层汇编语言,加了内存屏障

锁机制

  1. 乐观锁和悲观锁

乐观锁:提交的时候才上锁;CAS、加版本号
悲观锁:一开始就上锁。synchronized,ReentrantLock

  1. 可重入锁ReentrantLock

可重入锁,一个线程在获取锁后,可以再次获取自己的内部锁,避免死锁
ReentrantLock 是实现Lock接口的一个类。底层CAS+AQS
支持公平锁和非公平锁

  1. 读写锁、独占锁、共享锁、排他锁

ReentantReadWriteLock,读写锁。实现读写分离.是ReentrantWriteLock接口的具体实现

  1. 自旋锁

不加锁。等待的线程不阻塞,而是循环判断,满足条件得到锁。通过CAS

  1. 锁升级

无锁->偏向锁->轻量级锁->重量级锁
锁对象的对象头有一个threadId字段,在第一次访问的时候,字段为空,jvm让其持有偏向锁,threadId置为该线程id。再次进入的时候,先判断threadId是否与其线程id一致。否则就升级为轻量级锁。通过自旋一定次数获取锁,如果还是没有获得锁,那么就升级为重量级锁。
java6以后对锁进行了升级
目的:降低锁带来的性能消耗

  1. 锁的优缺点对比.
  • 偏向锁 :加锁解锁无需额外消耗;线程之间如果存在锁竞争,会带来撤销锁的额外消耗;适合一个线程访问同步块
  • 轻量级锁:线程不阻塞,提高响应速度;始终得不到锁竞争的线程,一直循环会给CPU带来开销;适合追求响应速度,同步代码块执行快的场景
  • 重量级锁
    不用自旋,CPU开销不大;线程阻塞,响应时间慢;追求吞吐量,同步代码块执行慢的场景
  1. synchronized和Lock、ReebtrantLock的区别
  • synchronized是jvm层面的,是关键字,Lock是接口,ReentrantLock是类
  • synchronized不能精确唤醒,ReentrantLock可以
  • synchronized不能中断
  • synchronized是非公平的。ReentrantLock可设置为公平锁
  • synchronized可用于代码块、类、方法、变量,ReentrantLock只能用在代码块锁
  • synchronized不用手动释放锁。ReentrantLock需要手动释放锁
  • 锁机制不同:syn底层操作对象头的mark word,ReentrantLock是CAS+AQS实现

线程池

  1. 底层核心

ThreadPoolExecutor 是线程池的核心
Executor提供工厂创建不同类型的线程池:创建固定线程数的线程池、只有一个线程的线程池、可扩容带缓冲的线程池
Executor是一个接口,用来执行Runnable任务(调用executor方法)
ExecutorService是比Executor更广泛的一个接口,可以执行Runnable任务、Callable任务。有返回值。且它提供控制线程池的方法
ExecutorService是Executor的子接口

  1. 线程池的参数

核心线程数、最大线程数、多余的闲置线程存活时间,存活时间单位,阻塞队列,线程工厂,拒绝策略

  1. 为什么要使用线程池

线程复用,降低资源消耗
提高响应速度:任务到了可以不需要等待线程创建好才执行
有效控制并发量
提高线程可管理性

  1. 提交任务时,线程池已满怎么办?

阻塞队列使用LinkedBlockingQueue:继续加入等待执行
阻塞队列使用ArrayBlockingQueue:拒绝策略

并发容器

ConcurrentHashMap

  1. 线程安全且高效的HashMap实现
  2. 使用分段锁的思想
  3. 如何实现线程安全的?
  • 1.6版本segment继承ReentrantLock充当锁,segment维护哈希列表的若干个桶
  • 1.8 使用CAS和synchronized保证并发安全

CopyOnWriteArrayList

  1. 写时复制
  2. 适合读多写少的场景
  3. 劣势:
  • 写的时候拷贝数组,消耗内存,如果原数组多会导致yong gc甚至full gc
  • 不能做到实时读取。拷贝、新增数据均需要时间,读取的时候可能还是旧的数据
  • 每次add或者set都需要拷贝数组,性能低
  1. 设计思想
  • 读写分析
  • 数据最终一致
  • 另开辟空间,解决并发冲突

Collections.synchronizedList

阻塞队列-线程同步的工具

BlockingQueue

  1. 实现类
  • ArrayBlockingQueue 数组结构组成的阻塞
  • LinkedBlockingQueue 链表结构组成的阻塞队列
  • SynchronousQueue 不存储元素的阻塞队列
  1. 什么是阻塞队列,为什么需要它?

队列满时插入元素会阻塞,队列空时取元素会阻塞的队列
常用于生产者消费者场景。socket客户端数据的读取和分析

CAS操作

  1. 比较并交换。循环获取数据,如果真实值和期望值不一致,就一直循环,直到一致就修改数据
  2. 缺点
  • ABA问题
  • 一直CAS失败,一直循环,CPU开销大
  • 只能保证一个共享变量的原子操作

JMM模型

  1. 虚拟的,实际不存在的。只是一种规范
  2. 主内存和线程的工作内存
  3. 可见性、有序性、原子性

ThreadLocal

  1. 本地线程副本变量工具类。每个线程都创建一个ThreadLocalMap对象。每个线程读取自己内部的ThreadLocalMap里的数据。避免资源在多线程共享
  2. 场景:为每个线程分配一个jdbc连接。线程间的jdbc连接互不影响
  3. 问题:

引起内存泄露,因为key是弱引用,value却是强引用
解决:每次用完ThreadLocal,调用remove方法,清楚数据
线程池情况下,用完记得清理

死锁

  1. 原因

互斥条件
请求并保持
不可剥夺
循环等待

  1. 如何解决

按顺序去申请资源
一次性申请所有资源
进一步申请资源时如果请求不到资源,就主动释放当前占用的资源。设置超时时间

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焦虑的说说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值