Java并发面试题, Java 中什么情况会导致死锁?如何避免?
Java并发面试题, Java 中什么情况会导致死锁?如何避免?
QA
Step 1
Q:: Java 中什么情况会导致死锁?如何避免?
A:: 死锁通常发生在两个或多个线程试图获取彼此持有的锁时,导致无限期等待。具体情况包括:1. 互斥条件:线程对所需资源独占。2. 持有并等待:线程在持有资源的同时,等待其他线程释放它所需要的资源。3. 不可剥夺:线程不能强制剥夺其他线程占有的资源。4.
环路等待:一组线程彼此形成一个环路,每个线程等待下一个线程所占有的资源。
避免死锁的方法:1. 避免嵌套锁:尽量减少嵌套锁的使用。2. 使用定时锁:使用 tryLock 等带有超时机制的锁。3. 避免长时间持有锁:尽量减少锁的持有时间。4.
资源排序:所有线程按相同顺序请求资源。
Step 2
Q:: 什么是 Java 内存模型(JMM)?
A:: Java 内存模型(Java Memory Model,
JMM)描述了 Java 程序中不同线程如何通过内存进行交互。JMM 规定了变量存储到内存和从内存中读取的方式,以确保 Java 程序在多线程环境中的正确性和一致性。具体来说,JMM 规定了 volatile、final 和 synchronized 关键字的行为,以确保线程间的可见性和有序性。
Step 3
Q:: 什么是 volatile 关键字?
A:: volatile 关键字用于声明一个变量可以被多个线程访问和修改。使用 volatile 变量时,JMM 确保所有线程都能看到该变量的最新值,并且对该变量的写操作对所有线程立即可见。volatile 变量不允许进行缓存优化,因此每次读取都是从主内存中读取,而不是从线程的工作内存中读取。
Step 4
Q:: 什么是 synchronized 关键字?
A:: synchronized 关键字用于实现线程间的互斥同步。当一个线程进入 synchronized 块时,它将持有该对象的监视器锁,其他线程必须等待该锁释放后才能进入该块。synchronized 可以用于方法或者代码块,以确保同一时刻只有一个线程执行被同步的方法或代码块。
Step 5
Q:: 什么是 ReentrantLock?如何使用它?
A:: ReentrantLock 是 java.util.concurrent.locks 包中的一个可重入锁,与 synchronized 类似。与 synchronized 不同,ReentrantLock 提供了更灵活的锁机制,例如支持公平锁、非阻塞的 tryLock 方法和可中断的锁等待等。使用 ReentrantLock 时,需要显式地调用 lock() 和 unlock()
方法来获取和释放锁。例如:
ReentrantLock lock = new ReentrantLock();
try {
lock.lock();
// 临界区代码
} finally {
lock.unlock();
}