产生死锁的一个示例
死锁产生的条件:线程之间互相持有对方需要的资源,互相依赖且无法释放,形成回环。
以下是一个示例代码。
环境:maven项目,使用了junit(也可以使用main方法)
maven依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>concurrency_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
java示例代码:
package concurrency.demo;
import org.junit.Assert;
import org.junit.Test;
public class DeadLockDemo {
private static String A = "A";
private static String B = "B";
private volatile boolean flag = false;
/**
* 测试产生死锁的代码。
* 实现死锁:
* 1、threadA依次需要A->B,中间sleep 一秒(确保持有资源)
* 2、threadB依次需要B->A,中间sleep 一秒(确保持有资源)
* threadA和threadB分别尝试将flag修改为true,如果flag最终为true,则有任意一个方法执行成功,否则失败(即产生了死锁)
*/
@Test
public void testGenDeadLock() throws InterruptedException {
Thread threadA = new Thread(() -> {
synchronized (A) {
System.out.println(Thread.currentThread().getName() + "持有:" + A);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (B) {
System.out.println(Thread.currentThread().getName() + "持有:" + B);
flag = true;
}
}
});
threadA.setName("threadA");
Thread threadB = new Thread(() -> {
synchronized (B) {
System.out.println(Thread.currentThread().getName() + "持有:" + B);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (A) {
System.out.println(Thread.currentThread().getName() + "持有:" + A);
flag = true;
}
}
});
threadB.setName("threadB");
// 启动线程,模拟死锁产生
threadA.start();
threadB.start();
// 将代码流程卡住,通过flag判断是否有方法执行完毕
while (flag == false) {
Thread.sleep(100L);
}
Assert.assertTrue(flag);
System.out.println("END");
}
}
最终结果:程序卡在while循环,无法运行到Assert.assertTrue(flag)语句。
控制台输出:
threadB持有:B
threadA持有:A
// 如果正常执行将会有
// threadB持有:A
// threadA持有:B
// END
表明死锁产生。