死锁是面试必不可缺的知识点,
上节说的线程中已经很明确的说明了死锁的解决方案。
那么什么时候会有多线程问题?
1: 多线程的环境下
2: 必须有共享资源
3: 对资源进行非原子性操作
用Java怎么重现死锁呢?
例子:
有N个资源和N个线程,并且你需要所有的资源来完成一个操作。
为了简单这里的n可以替换为2,越大的数据会使问题看起来更复杂。
通过避免Java中的死锁来得到关于死锁的更多信息。
/**
* 简单死锁程序
* lockA、lockB分别是两个资源,线程A、B必须同是拿到才能工作
*
但A线程先拿lockA、再拿lockB
* 线程B先拿lockB、再拿lockA
这样就导致了死锁,两个人都拿不到
*/
package net.health.ysk.admin;
/**
* 用Java模拟死锁
*
* @author wangtong
*/
public class DemoDeadLock {
private Object object1 = new Object();
private Object object2 = new Object();
public void a() {
System.out.println("a");
synchronized (object1) {
System.out.println("a-object1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object2) {
System.out.println("a-object2");
}
}
}
public void b() {
System.out.println("b");
synchronized (object2) {
System.out.println("b-object2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object1) {
System.out.println("b-object1");
}
}
}
public static void main(String[] args) {
DemoDeadLock demo = new DemoDeadLock();
System.out.println("111111111111111111111");
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("a-run");
demo.a();
}
}).start();;
System.out.println("22222222222222222222222");
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("b-run");
demo.b();
}
}).start();;
System.out.println("333333333333333333333");
}
}
执行该代码:
控制台打印结果:
111111111111111111111
22222222222222222222222
a-run
a
a-object1
333333333333333333333
b-run
b
b-object2
从这个打印结果就可以看出是发生了死锁,程序没有继续执行下去。
此时,a线程锁住了object1对象,正在等待,准备锁object2对象
b线程锁住了object2对象,正在登台,准备锁object1对象。
两个线程互相等待获取对方的锁,因此造成了死锁。
通过jconsole也可以明显的查看到死锁了:
意思是 线程1,正在等待线程0上的68ad31fc的锁