Java多线程——深入了解“死锁”
在了解“死锁”前,对“死锁”的知识进行简单的梳理,“死锁”知识无非就是:什么“死锁”?“死锁”怎样产生?死锁的影响?如何避免“死锁”?这四大问题。
众人皆知的“死锁”到底是什么?
1、“死锁”是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些线程都将无法向前推进的状态。
“死锁”到底是怎样产生的?
2、死锁的产生原因:对并发资源的加锁成“环”。
①互斥:共享资源在某一时刻只能被一个线程占用。
②占有且等待
:某线程拿到一个共享资源X占用后,还等待着被别的线程占用了的共享资源Y(该线程已经占有X,即要等待Y,还不释放X)。
③不可抢占:线程Thread1拿到对象锁x后,其他线程无法强行抢占x锁(需要等待Thread1执行完)。
④循环等待
:线程T1拿到了资源X的锁后,去申请Y的锁;
线程T2拿到了资源Y的锁后,去申请X的锁。
“死锁”对程序有什么影响?
3、在多线程中,“死锁”会造成线程的“假死”,严重影响程序的效率。
举个栗子,展示会出现“死锁”的情况
package com.xiaoaxiao.test.thread_test.book_test;
/**
* Created by xiaoaxiao on 2019/7/17
* Description: 死锁
*/
class DealThread implements Runnable{
public String username;
public Object lock1 = new Object();
public Object lock2 = new Object();
public void setFlag(String username){
this.username = username;
}
@Override
public void run() {
if (username.equals("a")){
synchronized (lock1){
try {
System.out.println("username = "+username);
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2){
System.out.println(" 按lock1->lock2 代码顺序执行");
}
}
}
if (username.equals("b")){
synchronized (lock2){
try {
System.out.println("username = "+username);
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1){
System.out.println(" 按lock2->lock1 代码顺序执行");
}
}
}
}
}
public class DealThreadTest {
public static void main(String[] args) {
try {
DealThread t1 = new DealThread();
t1.setFlag("a");
Thread thread1 = new Thread(t1);
thread1.start();
Thread.sleep(1000);
t1.setFlag("b");
Thread thread2 = new Thread(t1);
thread2.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
既然“死锁”对程序不好的影响如此之大,那应该如何避免“死锁”呢?