多线程练习--死锁
关于java的死锁可能网上一大堆的代码,作为初学者我觉得还是很有必要练习下,亲自实现,并分析其死锁的原理。
##死锁的原因: 因为两个或者多个进程互相需要对方手里的锁而进入了一种互相等待的状态。代码都是顺序执行的,所以不能倒退,也就没有办法交出手里的锁,这是一个大的前提。
##如何形成死锁: 举个两个进程死锁的例子。首先,死锁很重要的另一个前提就是锁的唯一性,我们都知道同步代码块需要传递一个对象,也就是我们说的锁。两个进程的死锁需要两把锁,此时就须要保证这两把锁都是唯一性,也就需要两把锁都是静态的对象,就像这样:
class LockTemp {
static final LockTemp l = new LockTemp ();
}
然后构造两个嵌套的同步代码块,如下代码所示:
synchronized (LockA.lock) {
System.out.println("进入外层同步代码块");
synchronized (LockB.lock) {
System.out.println("进入内层同步代码块");
}
}
两个代码块构造完成后,需要让一个t1进程进入A嵌套代码块的外层,另一个t2进程进入B嵌套代码块的外层,此时t1需要的另一锁在t2手上,t2需要的另一把锁在t1手上,所以进入了一种互相等待的状态,而这种等待的状态是没有办法结束的,所以程序进入了死锁状态。
完整的code:
package thread;
/*
* java多线程死锁的练习
*/
public class LockDemo {
public static void main(String[] args) {
// 来两个dead对象,一个为true,一个为false
Dead d1 = new Dead(true);
Dead d2 = new Dead(false);
// 创建两个进程对象并start
Thread t1 = new Thread(d1);
Thread t2 = new Thread(d2);
t1.start();
t2.start();
}
}
// 先来两把锁
class LockA {
static final LockA l = new LockA();
}
class LockB {
static final LockB l = new LockB();
}
// 实现死锁的类
class Dead implements Runnable {
// 定义一个私有的boolean变量,来决定线程进入同步代码的方向
private boolean flag;
public Dead(boolean flag) {
this.flag = flag;
}
public void run() {
while (true) {
if (flag == true) {
synchronized (LockA.l) {
System.out.println("if...A");
synchronized (LockB.l) {
System.out.println("if...B");
}
}
} else {
synchronized (LockB.l) {
System.out.println("else...B");
synchronized (LockA.l) {
System.out.println("else...A");
}
}
}
}
}
}