luckylbl

多线程面试题

多线程有几种实现方式?

  1. 继承Thread类
  2. 实现Runnable接口
  3. 实现Callable接口通过FutureTask包装器(同时实现了Future和Runnable接口)来创建Thread线程(创建FutureTask类实例,将实现了Callable的类放入FutureTask的构造方法,然后再将FutureTask的实例放入Thread的构造器,然后用Thread实例调用start())通过线程池创建线程,使用线程池接口ExecutorService结合Callable、Future实现有返回结果的多线程。

线程池

Runnable和 Callable有什么区别?

Runnable没有返回值,Callable可以拿到有返回值,Callable可以看作是 Runnable的补充。
Callable的返回值如果你在泛型中指定,返回值就是你指定的,如果你没有指定,默认是object

线程的状态?

初始化 就绪(实际不存在) 运行 阻塞 (计时等待 超时等待 同步阻塞) 终止

notify()和 notifyAll()有什么区别?

notifyAll()会唤醒所有的线程,notify()之后唤醒一个线程。
notifyAll() 调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。
notify()只会唤醒一个线程,具体唤醒哪一个线程由虚拟机控制。

run() 和 start() 区别?

start() 用于启动线程 只能调用一次
run() 用于执行线程的任务代码 可以多次调用

并发编程的三个重要特征

原子性 可见性 有序性

volatile关键字

volatile 是变量修饰符,可以保证内存可见性,有序性,不保证原子性,不会造成线程阻塞

synchronized 和 volatile 的区别是什么?

volatile 是变量(类变量和实例变量)修饰符;synchronized 是修饰方法、代码段。
volatile 仅能实现变量的修改可见性,有序性,不能保证原子性;而 synchronized 则可以保证变量的修改可见性和原子性,有序性。
volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞。

CAS:Compare and Swap

CAS 是一种原子操作,它包含三个主要参数:
    1. 内存值(Memory Value):需要更新的变量的当前值。
    2. 预期值(Expected Value):线程期望内存值为的值。
    3. 新值(New Value):如果预期值与内存值一致,则将内存值更新为这个新值。
	
CAS 的操作逻辑如下:
    • 如果内存值等于预期值,则将内存值更新为新值,并返回   true  。
    • 如果内存值不等于预期值,则不进行更新,并返回   false  。

CAS 的优点
    无锁机制:CAS 是一种无锁机制,不依赖传统的互斥锁(如   synchronized   或   ReentrantLock  )。它通过原子操作避免了线程之间的直接竞争,减少了锁的开销。
    高并发性能:在高并发场景下,CAS 可以显著提高性能,因为它避免了线程阻塞和上下文切换的开销。
    避免死锁:由于 CAS 不涉及锁的获取和释放,因此不会出现死锁问题。

synchronized 和 Lock 有什么区别

synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。
synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,机制上不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不当没有 unLock()去释放锁就会造成死锁

CAS/乐观锁在开发项目中的实践?

订单表和流水表,为了防止并发问题,就会加入CAS的校验过程,保证了线程的安全问题,但是看场景使用,并不是适用所有场景,优缺点都很明显.ABA的问题的话,加标志位,是使用version字段做的,之前我们只查询值是否匹配,现在我们要一同查出version字段也是否匹配.

posted on 2025-12-19 16:15  lubingliang  阅读(0)  评论(0)    收藏  举报

导航