并发编程面试题
在 java 中守护线程和本地线程区别
用户线程是程序创建的线程。
由jvm创建的线程是守护线程,比方说垃圾收集线程。
死锁与活锁的区别 ,死锁与饥饿的区别?
死锁 :是指两个或两个以上的进程( 或线程)在执行过程中 , 因争夺资源而造成的一种互相等待的现象 ,若无外力作用 , 它们都将无法推进下去。
活锁 :任务或者执行者没有被阻塞 , 由于某些条件没有满足 , 导致一直重复尝试 ,失败 , 尝试 ,失败。
饥饿 :一个或者多个线程因为种种原因无法获得所需要的资源 ,导致一直无法执行的状态。
如何在 Windows 和 Linux 上查找哪个线程使用的 CPU 时间最长?
top和jstack命令
Java Concurrency API 中的 Lock 接口(Lock interface)是什么?对比同步它有什么优势?
Lock 接口比同步方法和同步块提供了更具扩展性的锁操作。
synchronized只支持非公平锁。
什么是 Callable 和 Future?
Callable是有返回值的,这个返回值可以使用Future拿到。
在 Java 中 CycliBarriar 和 CountdownLatch 有什么区别?
CyclicBarrier 可以重复使用 , 而 CountdownLatch 不能重复使用。
CountDownLatch是门栓的意思,常用于并发编程中,它可以让多个线程都阻塞在一个地方,直到所有线程任务都执行完成。
常用方法:countDown方法和await方法。
await方法会的作用就是等待所有的线程都执行完了。countDown方法就是当某个线程执行完了任务之后就将count值进行减1.
应用场景:
并行任务同步:CountDownLatch用于协调多个并行任务的完成情况,确保所有任务都完成后再继续执行下一步操作。
多任务汇总:CountDownLatch可以用于统计多个线程的完成情况,以确定所有线程都以完成工作。
资源初始化:CountDownLatch可以用于等待资源的初始化完成,以边在初始化完成后开始使用。
CountDownLatch可以阻塞主线程,适用于需要同步返回的接口。
CyclicBarrier是循环栅栏的意思,他的特点是可以循环使用,当多个线程都到达同一个指定点的时候,再同时执行。
应用场景:CyclicBarrier可以用于将复杂的任务分配给多个线程执行,并在所有线程完成工作后触发后续的操作。
CyclicBarrier无法阻塞主线程,不适合在需要同步返回的接口中使用。CyclicBarrier适用于异步任务,尤其需要对子线程的执行结果做汇聚计算的更为适合,在大部分场景下,CountDownLatch能实现的功能,都能使用CyclicBarrier实现。
如何停止一个正在运行的线程?
使用 interrupt 方法终止线程,不推荐使用stop方法。
interrupt方法:会中断线程的休眠。说白了就是叫醒你起来继续干活。
stop方法:强行终止线程,可能会损坏正在处理的数据。
notify()和notifyAll()有什么区别?
notify只能唤醒一个线程,notifyall唤醒所有的线程。
乐观锁和悲观锁的理解及如何实现 ,有哪些实现方式?
cas就是一种乐观锁的实现方式。
什么叫线程安全?servlet 是线程安全吗?
Servlet 不是线程安全的。
SpringMVC 的 Controller 是线程安全的吗?不是的,和 Servlet 类似的处理流程。
可以使用ThreadLocal来实现多线程并发访问的问题。
volatile 有什么用?能否用一句话说明下 volatile 的应用场景?
volatile 保证内存可见性和禁止指令重排
在 java 中 wait 和 sleep 方法的不同?
最大的不同是在等待时 wait 会释放锁,而 sleep 一直持有锁。
什么是 ThreadLocal 变量?
Thread Local是线程隔离的变量,它让每个线程都拥有自己独立的变量副本。
什么是线程池? 为什么要使用它?
创建线程要花费昂贵的资源和时 间, 如 果任 务来 了才 创建 线 程那 么响 应时 间会 变长 ,
为了避免这些问题 , 在程序启动的时候就创建若干线程来响应处理 , 它们被称为线程池 , 里面的线程叫工作线程 。进而提高了程序的处理效率。
怎么检测一个线程是否拥有锁?
Thread类里面有一个holdsLock()方法
你如何在 Java 中获取线程堆栈?
jstack命令
Thread 类中的 yield 方法有什么作用?
使当前线程从执行状态( 运行状态) 变为可执行状态( 就绪状态)。
这玩意叫线程的礼让。
Java 中 ConcurrentHash Map 的并发度是什么?
TODO下来看看
Java 中 Semaphore 是什么?
Semaphore是信号量的意思,常用于并发编程中。用于控制同时访问某个资源的线程数量。Semaphore维护了一个计数器,线程可以通过acquire方法来获取许可证,可以通过release方法来释放许可证。当许可证数量为0的时候,再来线程将被阻塞。
Semaphore底层也支持公平锁和非公平锁。当使用公平锁的时候,下一个被执行任务的线程一定是等待时间最久的那个线程。
应用场景:
限流:Semaphore可以用于限制对共享资源的并发访问数量,以控制系统的流量。
资源池:Semaphore可以用于实现资源池,以维护一组有限的共享资源。
Java 中的 ReadWriteLock 是什么?
ReentrantReadWriteLock是读写锁,常用于java编程中。它允许多个线程同时读取数据,但只允许一个线程写入数据。在某些情况下,比方说读多写少的场景中,使用这个类可以提高程序的性能和可靠性。
应用场景:主要用于读多写少的场景。比如:在数据库连接池中,多个线程可能需要同时访问数据库,但是只有一个线程能够执行写操作,如插入、更新或删除数据。使用reentrantreadwritelock可以在保证数据一致性的同时提高并发性能。
你对线程优先级的理解是什么?
1 代表最低优先级 , 10 代表最高优先级。
同步方法和同步模块 ,哪个是更好的选择?
同步块是更好的选择 , 因为它不会锁住整个对象( 当然你也可以让它锁住整个对象) 。
同步方法会锁住整个对象 , 哪怕这个类中有多个不相关联的同步块 , 这通常会导致他们停止执行并需要等待获得这个对象上的锁。
什么是 CAS
CAS 是 compare and swap 的缩写 , 即我们所说的比较交换
Java中基于Unsafe的类提供了对CAS的操作的方法,JVM会帮助我们将方法实现CAS汇编指令。
CAS 的问题
ABA问题
不能保证代码块的原子性
CAS 机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。 比如需 要保证 3
个变量共同进行原子性的更新 , 就不得不使用 synchronized 了。
造成CPU利用率的增加
什么是Future?
通过实现 Callback 接口 , 并用Future 可以来接收多线程的执行结果。
Future 表示一个可能还没有完成的异步任务的结果 , 针对这个结果可以添加 Callback 以便在任务执行成功或失败后做出相应的操作。
package java.util.concurrent;
public interface Future<V> {
boolean cancel(boolean var1);
boolean isCancelled();
// 判断线程任务有没有执行完
boolean isDone();
// 阻塞等待结果
V get() throws InterruptedException, ExecutionException;
// 阻塞等待结果,有超时时间
V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException;
}
ThreadPoolExecutor#submit() 返回 Future对象。
什么是 AQS
AQS 是 AbustactQueuedSynchronizer 的简称 , T他是一个抽象类,JUC下面的很多内容都是基于AQS来实现的。
首先,AQS中提供了一个由volatile修饰,并且采用CAS方式修改的int类型的state变量。
其次,AQS红维护了一个双向链表,有head,有tail,并且每个节点都是Node对象。
其底层提供了获取锁和释放锁等等的逻辑。
state表示线程的同步状态,也叫做锁的持有计数。
AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大 量的同步器 , 比如我们提到的 ReentrantLock , Semaphore ,其他的诸如 ReentrantReadWriteLock ,SynchronousQueue , FutureTask 等等皆是基于 AQS 的。
AQS 支持两种同步方式 :
1 、 独占式
2 、 共享式
这个我们可以看aqs的源码中Node节点定义的类型能够看到,说白了就是你追加的是独占节点还是共享节点。
FutureTask 是什么
这个其实前面有提到过,FutureTask 表示一个异步运算的任务。
FutureTask 里面可以传 入一个 Callable 的具体实现类 , 可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。
当然 ,由于 FutureTask 也是 Runnable 接口的实现类 ,所以 FutureTask 也可以放入线程池中。
Java 中用到的线程调度算法是什么
抢占式
并发编程三要素(面试有被问到)
原子性、有序性、可见性