参考文章
码农翻身 一书中的第一个故事“我是一个线程”
思路
如果有两个锁 L1 L2, 线程 t1 持有 L1 且在尝试获取 L2, 线程 t2 持有 L2 且在尝试获取 L1 那么就会出现死锁了
程序
用 synchronized 语句块实现
我们可以在 class 对象上加锁
具体如下
public class DeadLock {
public static void main(String[] args) throws Exception {
class Naive implements Runnable {
private final Class c1;
private final Class c2;
private String name;
private Naive(String name, Class c1, Class c2) {
this.name = name;
this.c1 = c1;
this.c2 = c2;
}
@Override
public void run() {
synchronized (c1) {
try {
// 让另一个线程有机会被调度, 这样另一个线程就有机会获得 c2 对应的锁了
Thread.sleep(1000);
System.out.println(String.format("%s acquired %s", name, c1));
synchronized (c2) {
System.out.println(String.format("%s acquired %s", name, c2));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Thread t1 = new Thread(new Naive("t1", Integer.class, String.class));
Thread t2 = new Thread(new Naive("t2", String.class, Integer.class));
t1.start();
t2.start();
t1.join();
t2.join();
}
}
运行结果如下
运行结果
用 ReentrantLock 来实现
也可以用 ReentrantLock 来实现,程序如下
package com.coder.rising;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class DeadLock {
public static void main(String[] args) throws Exception {
class Naive implements Runnable {
private final Lock lock1;
private final Lock lock2;
private String name;
private Naive(String name, Lock lock1, Lock lock2) {
this.name = name;
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
lock1.lock();
try {
// 让另一个线程有机会被调度, 这样另一个线程就有机会获得 lock2 对应的锁了
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(String.format("%s acquired %s", name, lock1));
lock2.lock();
System.out.println(String.format("%s acquired %s", name, lock2));
lock2.unlock();
lock1.unlock();
}
}
Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();
Thread t1 = new Thread(new Naive("t1", lock1, lock2));
Thread t2 = new Thread(new Naive("t2", lock2, lock1));
t1.start();
t2.start();
t1.join();
t2.join();
}
}
运行结果如下
运行结果