死琐
A线程持有a锁,等待获取b锁;同时B线程持有b锁,等待获取a锁。
死琐条件
-- 独占锁:
- 互斥:资源不能被共享,只能由一个进程使用。
- 请求与保持:进程已获得了一些资源,但因请求其它资源被阻塞时,对已获得的资源保持不放。
- 不可抢占:有些系统资源是不可抢占的,当某个进程已获得这种资源后,系统不能强行收回,只能由进程使用完时自己释放。
-- 循环等待:若干个进程形成环形链,每个都占用对方申请的下一个资源。
public static void main(String[] args) {
final Object a = new Object();
final Object b = new Object();
Thread threadA = new Thread(() -> {
synchronized (a) { //sleep 下可以确保死锁
System.out.println("now i in threadA-locka");
synchronized (b) {
System.out.println("now i in threadA-lockb");
}
}
});
Thread threadB = new Thread(() -> {
synchronized (b) { //sleep 下可以确保死锁
System.out.println("now i in threadB-lockb");
synchronized (a) {
System.out.println("now i in threadB-locka");
}
}
});
threadA.start();
threadB.start();
}
如何避免
- 避免多个线程互相持有对方线程所需要的独占锁的的情况
- 设置优先级
- 超时放弃
ReentrantLock接口中: boolean tryLock(long time, TimeUnit unit)
设置超时时间,超时可以退出防止死锁。
- 特定顺序 A->B->C
- 尽量降低锁的使用粒度,尽量不要几个功能用同一把锁,能锁块不锁方法
- 不要用锁
- 用Concurrent类。比较常用的是ConcurrentHashMap、ConcurrentLinkedQueue、
原子操作。AtomicBoolean等,实际应用中java.util.concurrent.atomic十分有用,简单方便且效率比使用Lock更高
银行家算法
- 条件:
- 固定数量的进程,固定数量的资源
- 进程预先指定工作所需最大资源
- 进程不能申请比总资源还多的资源
- 进程等待时间有限
- 进程在有限时间使用资源,用完归还
-
符号:
Available 系统可用资源数
Max[i] 进程i对资源的最大需求
Allocation[i] 进程i得到的资源数
Need[i] 进程i还需要的资源数
Request[i] 进程i当前申请的资源数 -
步骤:
- Request[i] <= need[i]
- Request[i] <= Available
- 分配资源,调整状态
Available = Available - Request[i]
Allocation[i] = Allocation[i] + Request[i]
Need[i] = Need[i] - Request[i] - 判断新状态是否有效,无效则退回,进程等待
初始化:Work = Available, finished = false
检测:Need[i] <= Work
检测死锁
-
jstack
Jstack工具可以用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。
jps 查端口号
jstack pid
-
jconsole
图形化工具
网友评论