死锁是在多线程情况下最严重的问题,在多线程对公共资源(文件,数据)等进行操作时,彼此不释放自己的资源,而去试图操作其他线程的资源,而形成的交叉引用,就会产生死锁。
假如我有一个需求,有一个线程,先写入A文件,在顺序写入B文件,再保存起来。还有另一个线程,先写入B文件,再顺序写入A文件,再保存起来。代码如下:
private static String fileA = "A文件";
private static String filedB = "B文件";
public static void main(String[] args) {
new Thread() { //线程1
//重写run方法
public void run() {
while (true) {
synchronized (fileA) {//打开文件A,线程独占fileA
System.out.println(this.getName() + ":文件A写入");
synchronized (filedB) {
System.out.println(this.getName() + ":文件B写入");
}
System.out.println(this.getName() + ":所有文件保存");
}
}
}
}.start();
new Thread() { //线程2
//重写run方法
public void run() {
while (true) {
synchronized (filedB) {//打开文件B,线程独占filedB
System.out.println(this.getName() + ":文件B写入");
synchronized (fileA) {
System.out.println(this.getName() + ":文件A写入");
}
System.out.println(this.getName() + ":所有文件保存");
}
}
}
}.start();
}
我们把线程2注释的话,只运行线程1,那么就会无尽的写入,不会产生死锁,相反我们把线程1注释,运行线程2,也是会无尽的写入只是顺序不同,当两个线程都运行,结果如下:
程序还在运行,但是不继续走了,因为产生了死锁
观察发现thread-0这个线程只把A写入了,到了thread-1线程把B写入以后也进行堵死了,原因出在synchronized锁住某一个对 象,线程1已经持有A文件了,线程2已经持有B文件了,那么线程1还想访问B文件,或者线程2还想访问A文件,双方都没有释放,双方还在进行调用,那么死锁产生了。
那么解决死锁的建议是:
-尽量减少公共资源的引用,用完马上释放
-用完马上释放公共资源
-减少Synchronized使用,采用”副本”方式替代
在这个例子里呢,改成两个程序锁住的对象顺序一致就可以了,要么一段一段执行,防止死锁,但是减少Synchronized使用,采用”副本”方式替代,我学习的视频在这个使用方面还没有相应的讲解,但是说是后续会有这些讲解,如果学习的话后续添加