死锁问题
什么是死锁?
- 当多个线程被同时阻塞无法正常运行,都在等待获取锁资源时就会发生死锁现象。
- 此时程序不会报出任何异常,也不会终止运行
死锁产生
- 线程互斥:假设我们为当前方法上了锁,那么某一时刻就只有一个线程可以进入执行,当该线程进入后我们就视为该线程获得了锁资源,此时其他线程无法获得锁资源也就无法进入被锁代码块执行。此时已经进入执行的线程与其他线程就属于互斥关系
/* 示例代码 */
MyRunnable task1 = new MyRunnable();
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task1);
t1.start();
t2.start();
class MyRunnable implements Runnable{
@Override
public synchronized void run() {
for (int i = 1; i < 10; i++) {
System.out.println("线程执行体\t"+i);
}
}
}
/* 此时t1线程与t2线程就是互斥关系
假设t1线程先进入同步块,那么t2线程必须等待t1线程执行完毕才能进入执行*/
- 不可剥夺:本线程所占有的资源不可被其他线程强行获取,依旧以上述代码为例,当t1线程执行过程中,t2不能强行获取锁资源
- 请求和保持:当资源请求者再请求获得资源的同时,仍然保持占有原有的资源
- 循环等待:指当A1需要获得A2的资源,同时A2需要获得A1的资源,则双方都会进入一个资源阻塞的条件无法正常运行(形成闭环)
死锁示例
/* 必然死锁 */
public class Demo01 {
private static Object obj1 = new Thread();
private static Object obj2 = new Thread();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj1){
System.out.println("线程1占用资源1,请求获得资源2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj2){
System.out.println("线程1成功获取资源2");
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj2){
System.out.println("线程2占用资源2,请求获得资源1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj1){
System.out.println("线程2成功获取资源1");
}
}
}
}).start();
}
}