并发编程初级面试题

本贴最后更新于 977 天前,其中的信息可能已经时移世易

并发编程初级面试题

一. 什么是进程和什么是线程

进程是操作系统资源分配和调度的基本单位, 也可以说一个程序就是一个进程, 可以看成是程序的实例

线程是操作系统资源分配和调度的最小单位, 他被包含在进程之中, 是进程中的实际运作单位

二. 线程的状态

  • new(新建)
  • runnable(运行)
  • blocked(阻塞)
  • waiting(等待)
  • timed_waiting(超时等待)
  • terminated(终结)

三. wait 和 sleep 的区别

  • wait 是 Object 的方法, 调用 wait 会释放锁
  • sleep 是 Thread 的方法, 调用 sleep 不会释放锁

四. 创建线程的方式

  1. 继承 Thread, 重写 run 方法
  2. 实现 Runnable, 扔到 thread 里运行
  3. 实现 Callable, 扔到 FutureTask 中, 再把 FutureTask 扔到 thread 里运行
  4. 使用线程池创建

五. 线程池的创建方式和 7 个参数

  1. Executors.newCachedThreadPool()

    全是救急线程的线程池

  2. Executors.newFixedThreadPool()

    可以设置线程数量的线程池

  3. Executors.newScheduledThreadPool()

    定时执行任务的线程池

  4. Executors.newSingleThreadExecutor()

    创建只有 1 个线程的线程池

  5. 手动 new ThreadPoolExecutor(...)

    根据阿里巴巴开发手册, 不准使用以上方法创建线程池, 所以需要手动创建线程池, 手动创建线程池就需要了解创建线程池的 7 个参数

    1. 核心线程数量
    2. 最大线程数量
    3. 存活时间
    4. 时间单位
    5. 阻塞队列
    6. 线程工厂
    7. 拒绝策略(队列满了之后的行为)
      1. 丢弃任务, 并且抛异常
      2. 在调用者线程执行任务, 如果线程池已经 shutdown, 则丢弃任务
      3. 丢弃等待最久的任务, 把当前任务加入进去
      4. 丢弃任务, 不抛异常, 什么都不做

六. ForkJoinPool

ForkJoinPool 的核心思想是大任务拆成小任务, 最终合并结果

ForkJoinPool 使用工作窃取算法, 当某个线程的任务队列中没有可执行任务的时候, 从其他线程的任务队列中窃取任务来执行, 可以充分的压榨 CPU 资源

七. 常用的并发工具类

  1. ReentrantLock
  2. AtomicInteger
  3. LongAdder
  4. CopyOnWriteArrayList
  5. CopyOnWriteArraySet
  6. ConcurrentHashMap
  7. CountDownLatch
  8. CyclicBarrier
  9. Semaphore
  10. BlockingQueue
  11. 线程池

八. CountDownLatch 和 CyclicBarrier 的区别

CountDownLatch CyclicBarrier
减数字 加数字
数字为 0 时释放所有等待的线程 数字加到规定的值时释放所有等待线程, 并且可以执行构造函数传入的任务(可选)
数字无法重置 数字加到规定的值时, 重新从 0 开始加
调用 await()方法只进行阻塞 调用 await()方法数字加 1, 如果加完数字还是没有达到规定的值, 阻塞等待
不可重复利用 可重复利用

九. CAS 和 volatile

CAS 是乐观锁, 先比较, 再修改, 内存位置(JAVA 中的内存地址, V), 旧的预期值(A)和新值(B), 如果 V 和 A 一样就改成 B, JDK9 之前 CAS 是通过 Unsafe 对象操作, JDK9 之后推荐通过 VarHandle, 所以 JUC 包里面的 CAS 操作都变了

volatile 是 java 的关键字, 作用主要是保证内存可见性和禁止指令重排序

十. synchronized 和 ReentrantLock 的区别

  1. synchronized 是 java 关键字, ReentrantLock 是 Lock 接口的实现类
  2. synchronized 在发生异常时, 会释放锁, ReentrantLock 不会
  3. ReentrantLock 可以打断等待, synchronized 不行
  4. ReentrantLock 可以知道有没有获取锁, synchronized 不行
  5. ReentrantLock 是乐观锁, 而且可以控制是否公平, synchronized 严格来说是悲观锁(锁升级之后)
  6. ReentrantLock 有 Condition, 可以唤醒特定的组

十一. ReentrantReadWriteLock 读写锁

  1. 读读共享, 读写, 写写互斥
  2. 可能造成线程饥饿
  3. 写锁可以降级到读锁, 读锁不能升级成写锁
  4. JDK8 加入了新的读写锁, StampLock, 支持乐观读

十二. Java 中如何获取到线程 dump 文件

  1. 获取到线程的 pid,可以通过使用 jps 命令,在 Linux 环境下还可以使用 ps -ef | grep java
  2. 打印线程堆栈,可以通过使用 jstack pid 命令,在 Linux 环境下还可以使用 kill -3 pid
  3. 使用 jconsole 查看

十三. Java 中用到的线程调度算法是什么

Java 虚拟机采用抢占式调度模型

十四. LockSupport

LockSupport.park 不需要获取锁资源就能阻塞线程, 而且可以精确控制唤醒的线程, 并且可以在线程没有阻塞之前提前 unpark, 这时候线程运行到 park 方法的时候不会阻塞, JUC 工具包里的阻塞等待就是靠 park 方法实现

十五. ThreadLocal

每个线程内部有 1 个 ThreadLocalMap, 当调用 threadLocal 的 get, set, remove 方法时, 在方法内部拿到当前线程, 从线程中获取 ThreadLocalMap, 最后以 threadLocal(弱引用)为 key, 从中取出数据

使用 ThreadLocal 是线程安全的, 但是使用完需要及时删除, 否则会造成一定程度的内存泄漏或浪费(因为 ThreadLocalMap 的 key 使用的是弱引用包装的 threadLocal)

十六. synchronized 锁升级

  1. 无锁

    无锁就是正常对象状态, 一般新创建的对象状态为无锁可偏向

  2. 偏向锁

    在对象头的 mark word 上记录线程 ID, 代表当前线程获取了锁

    1. 如果发生锁竞争, 会升级成轻量级锁
    2. 如果在 synchronized 之外调用 hashcode 方法, 锁会升级成轻量级锁
    3. 如果在 synchronized 之内调用 hashcode 方法, 锁会升级成重量级锁
    4. 偏向锁同一线程 ID 修改次数达到 20 次后会发生批量重偏向(剩余锁对象的偏向全部修改成该线程 ID)
    5. 偏向锁同一线程 ID 修改次数达到 40 次后会关闭整个类的所有对象的偏向锁, 变成不可偏向状态
  3. 轻量级锁 + 自旋锁

    对象头的 mark word 上会记录线程栈中的锁记录引用, 如果多次 CAS 操作失败, 会升级成重量级锁

    CAS 次数 JDK6 之前是默认 10 次, JDK6 的时候是自适应次数

  4. 重量级锁(管程 Monitor)

    在对象头的 mark word 上记录 Monitor 的引用, 没有获取锁的线程会加入 Monitor 的 EntryList 中, 调用 wait 的线程会加入 WaitSet 中, Owner 记录的是锁的拥有者

  5. 锁消除

    synchronized 的对象是局部变量, 并且 JVM 发现没有逃出, 会优化成不加锁

  6. 锁粗化

    当一段代码中有 2 个或多个 synchronized 代码块, 并且中间的代码非常少, 而且运行的很快, 会优化成一个 synchronized

十七. AQS

AbstractQueuedSynchronizer 简称 AQS, 是个抽象类, JUC 大部分工具类都依赖他实现, 内部拥有 1 个 volatile 修饰是 state 和 1 个等待队列一对头尾节点(链表实现队列), 通过 CAS 修改 state 来判断是否获取锁, 如果没有获取锁, 把当前线程加入等待队列并且 park 阻塞

AQS 支持两种同步方式, 公平和非公平

  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    324 引用 • 1395 回帖
  • JUC
    17 引用 • 3 回帖 • 1 关注
  • 线程
    120 引用 • 111 回帖 • 3 关注
2 操作
xiaokedamowang 在 2021-08-23 10:15:39 更新了该帖
xiaokedamowang 在 2021-08-21 09:32:58 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...