线程死锁
一、产生死锁的原因
要知道为什么会产生死锁,首先我们需要知道,线程同步
当两个或两个以上的线程需要共享资源时,它们需要某种方法来确定 资源在某一刻仅被一个线程占用 。达到此目的 的过程叫做同步(synchroniztion)
同步的关键是 管程 (也叫信号量semaphore)的概念。管程是一个互斥独占锁定的对象 ,或称 互斥体(mutex) 。
在给定的时间,仅有一个线程可以获得管程。
当一个线程需要锁定,他必须进入管程。所有其他试图进入已近锁定的管程 的线程必须挂起直到第一个线程退出管程。这些其他的线程被称为 等待管程。一个拥有管程的线程如果愿意的话可以再次进入相同的管程
二、线程死锁
上面介绍了管程再来看这里就会很容易理解死锁了
所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。
因此我们举个例子来描述,如果此时有一个线程A,按照先锁key1再获得锁key2的的顺序获得锁,而在此同时又有另外一个线程B,按照先锁key2再锁key1的顺序获得锁。就会产生死锁
例如下面这段代码所示:
线程张三和李四,分别代表上面的线程A和B
public class DeadLlock {
//死锁例子
//成员内部类
public class Lock implements Runnable{
//这是两把锁对象 key1和key2
private Object key1=new Object();
private Object key2=new Object();
//用于控制线程拿钥匙顺序
private boolean flag=true;
@Override
public void run() {
if(flag) {
flag=false;
synchronized(key1) {
System.out.println(Thread.currentThread().getName()+" key1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized(key2) {
System.out.println(Thread.currentThread().getName()+" key2");
}
}
}else {
flag=true;
synchronized(key2) {
System.out.println(Thread.currentThread().getName()+" key2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized(key1) {
System.out.println(Thread.currentThread().getName()+" key1");
}
}
}
}
}
public void myrun() {
Lock l=new Lock();
Thread t1=new Thread(l,"张三");
Thread t2=new Thread(l,"李四");
t1.start();
t2.start();
}
public static void main(String[] args) {
DeadLlock dl=new DeadLlock();
dl.myrun();
}
}