线程死锁
需求背景
还是两个线程模拟卖火车票的场景,不过这个时候我们加上一些别的控制,来让程序产生死锁的现象,先上代码:
public class ThreadTest02 implements Runnable {
private static Integer count = 100;
private Object obj = new Object();
public boolean flag = true;
@Override
public void run() {
//当票的数量小于100的时候都调用买票方法
if (flag) {
while (count > 0) {
synchronized (obj) {
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
saleTicket();
}
}
} else {
while (count > 0) {
saleTicket();
}
}
}
private synchronized void saleTicket() {
synchronized (obj) {
if (count > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName() + "卖了第【" + (100 - count + 1) + "】张票");
count--;
} else {
System.out.println("票已售完.....");
}
}
}
/**
* 使用两个线程模拟两个窗口卖火车票
*/
public static void main(String[] args) {
ThreadTest02 windowThread1 = new ThreadTest02();
//创建窗口1线程
Thread thread1 = new Thread(windowThread1, "窗口【1】");
//创建窗口2线程
Thread thread2 = new Thread(windowThread1, "窗口【2】");
//启动两个线程
thread1.start();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
windowThread1.flag = false;
thread2.start();
}
}
代码分析
为什么以上代码会产生死锁呢?
- thread1启动的时候
flag=true
,这个时候start起来的话则获取到了一把obj
锁,这个时候故意让这个线程休眠400毫秒,如下代码:
- 在thread1还在休眠的时候,将flag设置成false,同时启动 thread2线程,这个时候thread2走到了else的代码块中,直接调用saleTicket方法,这个时候thread2获取到了一把
this
锁,同时等待obj锁,如下图:
产生这个死锁的原因是什么?
因为saleTicket方法的synchronized使用了嵌套锁,本身方法是this锁,而方法块又是obj锁,所以整个程序就产生了死锁: