死锁产生的四个必要条件:
- 资源互斥:一个资源只能被一个线程使用
- 循环等待:若干线程形成头尾相接的循环等待关系
- 不可剥夺:线程已经获取的资源,在未使用完之前,不能强行剥夺
- 请求与保持:一个线程因请求资源而阻塞时,对已经占有的资源保持不放
java 死锁:
package MutileThread;
class deadLock implements Runnable{
String lockA;
String lockB;
public deadLock(String lockA, String lockB)
{
this.lockA = lockA;
this.lockB = lockB;
}
@Override
public void run()
{
synchronized(lockA)
{
System.out.println(String.format("Thread %s has %s, need %s",Thread.currentThread().getName(),lockA,lockB));
synchronized (lockB)
{
}
}
}
}
public class RdeadLock {
public static void main(String[] args) {
String lockA = "lockA";
String lockB = "lockB";
new Thread(new deadLock(lockA,lockB),"a").start();
new Thread(new deadLock(lockB,lockA),"b").start();
}
}
死锁检测
- jps 定位java进程
- jstack pid
死锁避免:
- 指定锁的顺序。比如在例子中,添加条件,只有在获取锁A的情况下,才能获取锁B,即可避免死锁。
- 粗锁法:> 一个粒度粗的锁来消除“请求与保持条件”,缺点是会明显降低程序的并发性能并且会导致资源的浪费
- 显示锁ReentrantLock.try(long,TimeUnit)来申请锁
- 银行家算法
摘自:https://zh.wikipedia.org/wiki/%E9%93%B6%E8%A1%8C%E5%AE%B6%E7%AE%97%E6%B3%95
每一行为一个进程,初始为false,
通过每一个行的最大资源 - 已经分配的资源,得到Need矩阵;判断还能获取的资源,符合哪个进程的need,将 aviatiable 分配给该进程,之后释放该进程的资源,设为true,并将资源数加到available向量上。依次类推,直到所有进程都为true。