何为死锁呢?
死锁指两个或两个以上的进程在执行过程中
由于竞争资源或由于彼此通信而造成的一种阻塞的现象,如果没有外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,在日常开发中,如果不进行合理的逻辑规划,很有可能出现死锁现象,那么我们如何避免死锁的现象发生
下文是笔者准备的死锁避免方法,如下所示:
避免死锁的方法:
1.不使用synchronized这个显式的锁,而采用信号量控制资源,可被多少线程访问
2.当设置资源只可被一个线程访问时,则此时为锁住状态,
信号量中可设置获取的超时时间,
对无法成功获取,可进行重复尝试,或指定尝试次数后,也可立即退出
例:
使用信号量控制死锁
package com.java265.other;
import java.util.Date;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class Test16 {
public static String obj1 = "java265.com-1";
public static final Semaphore a1 = new Semaphore(1);
public static String obj2 = "java265.com-2";
public static final Semaphore a2 = new Semaphore(1);
public static void main(String[] args) {
LockAa a = new LockAa();
new Thread(a).start();
LockBb b = new LockBb();
new Thread(b).start();
}
}
class LockAa implements Runnable {
public void run() {
try {
System.out.println(new Date().toString() + " LockA 开始执行");
while (true) {
if (Test16.a1.tryAcquire(1, TimeUnit.SECONDS)) {
System.out.println(new Date().toString() + " LockA 锁住 obj1");
if (Test16.a2.tryAcquire(1, TimeUnit.SECONDS)) {
System.out.println(new Date().toString() + " LockA 锁住 obj2");
Thread.sleep(60 * 1000); // do something
} else {
System.out.println(new Date().toString() + "LockA 锁 obj2 失败");
}
} else {
System.out.println(new Date().toString() + "LockA 锁 obj1 失败");
}
Test16.a1.release(); // 释放
Test16.a2.release();
Thread.sleep(1000); // 马上进行尝试,现实情况下do something是不确定的
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class LockBb implements Runnable {
public void run() {
try {
System.out.println("java265.com " + new Date().toString() + " LockB 开始执行");
while (true) {
if (Test16.a2.tryAcquire(1, TimeUnit.SECONDS)) {
System.out.println(new Date().toString() + " LockB 锁住 obj2");
if (Test16.a1.tryAcquire(1, TimeUnit.SECONDS)) {
System.out.println(new Date().toString() + " LockB 锁住 obj1");
Thread.sleep(60 * 1000); // do something
} else {
System.out.println(new Date().toString() + "LockB 锁 obj1 失败");
}
} else {
System.out.println(new Date().toString() + "LockB 锁 obj2 失败");
}
Test16.a1.release(); // 释放
Test16.a2.release();
Thread.sleep(10 * 1000);
// 这里只是为了演示,所以tryAcquire只用1秒,而且B要给A让出能执行的时间,否则两个永远是死锁
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
-----运行以上代码,将输出以下信息-----
Thu Apr 28 23:01:32 CST 2022 LockA 开始执行
java265.com Thu Apr 28 23:01:32 CST 2022 LockB 开始执行
Thu Apr 28 23:01:32 CST 2022 LockA 锁住 obj1
Thu Apr 28 23:01:32 CST 2022 LockB 锁住 obj2
Thu Apr 28 23:01:33 CST 2022LockB 锁 obj1 失败
Thu Apr 28 23:01:33 CST 2022LockA 锁 obj2 失败
Thu Apr 28 23:01:34 CST 2022 LockA 锁住 obj1
Thu Apr 28 23:01:34 CST 2022 LockA 锁住 obj2
Thu Apr 28 23:01:43 CST 2022 LockB 锁住 obj2
Thu Apr 28 23:01:43 CST 2022 LockB 锁住 obj1
Thu Apr 28 23:02:35 CST 2022 LockA 锁住 obj1
Thu Apr 28 23:02:35 CST 2022 LockA 锁住 obj2