返回

Java并发编程如何防止死锁?

发布时间:2022-11-24 09:48:14 265

死锁可能是大家都不想遇到的问题,因为一旦程序出现死锁,如果没有外力的话,程序会因为资源竞争一直处于假死状态。

死锁示例代码如下:

public class

public static String OBJECT_1 = "OBJECT_1";
public static String OBJECT_2 =
"OBJECT_2";

public static void main(String[] args) {
LockA lockA = new LockA();
new Thread(lockA).start();

LockB lockB = new LockB();
new Thread(lockB).start();
}

}

class

@Override
public void run() {
synchronized (DeadLockTest.OBJECT_1) {
try {
Thread.sleep(500);

synchronized (DeadLockTest.OBJECT_2) {
System.out.println(
"LockA");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

class

@Override
public void run() {
synchronized (DeadLockTest.OBJECT_2) {
try {
Thread.sleep(500);

synchronized (DeadLockTest.OBJECT_1) {
System.out.println(
"LockB");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

} 当一个线程获得了 OBJECT_1 锁时,它并没有释放锁,然后再申请 OBJECT_2 锁。

这时,另一个线程获取了OBJECT_2锁,并没有释放锁去申请OBJECT_1锁。

由于 OBJECT_1 和 OBJECT_2 锁都没有被释放,所以两个线程会一起请求,陷入死循环,即出现死锁情况。

那么如果避免了死锁问题呢?

1. 缩小锁的范围。

死锁情况可能是如上锁范围过大造成的。

那么,解决方案就是缩小锁的范围。

class

@Override
public void run() {
synchronized (DeadLockTest.OBJECT_1) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (DeadLockTest.OBJECT_2) {
System.out.println("LockA");
}
}

}

class

@Override
public void run() {
synchronized (DeadLockTest.OBJECT_2) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (DeadLockTest.OBJECT_1) {
System.out.println(
"LockB");
}
}

} 在获取 OBJECT_1 锁的代码块中,不包含获取 OBJECT_2 锁的代码。

同时,获取OBJECT_2锁的代码块中不包含获取OBJECT_1锁的代码。

2. 保证锁的顺序。

在死锁的情况下,线程获取锁的顺序是OBJECT_1和OBJECT_2。

另一个线程以相反的顺序获取锁:OBJECT_2 和 OBJECT_1。

那么,如果我们能保证每次获取锁的顺序都是一样的,就不会出现死锁问题。

class

@Override
public void run() {
synchronized (DeadLockTest.OBJECT_1) {
try {
Thread.sleep(500);

synchronized (DeadLockTest.OBJECT_2) {
System.out.println("LockA");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

class

@Override
public void run() {
synchronized (DeadLockTest.OBJECT_1) {
try {
Thread.sleep(500);

synchronized (DeadLockTest.OBJECT_2) {
System.out.println(
"LockB");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

} 两个线程,每个线程先获取 OBJECT_1 锁,然后再获取 OBJECT_2 锁。

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
从零开始轻松部署Docker Swarm集群 2022-11-24 09:22:31