当业务比较复杂,多线程应用里有可能会发生死锁
死锁产生的原因
- 线程1 首先占有对象1,接着试图占有对象2
- 线程2 首先占有对象2,接着试图占有对象1
- 线程1 等待线程2释放对象2
- 与此同时,线程2等待线程1释放对象1
就会。。。一直等待下去,直到永远循环下去。
代码演示形成死锁
package multiplethread;
import charactor.Hero;
public class TestThread5 {
public static void main(String[] args) {
final Hero ahri = new Hero();
ahri.name = "九尾妖狐";
final Hero annie = new Hero();
annie.name = "安妮";
Thread t1 = new Thread(){
public void run(){
//占有九尾妖狐
synchronized (ahri) {
System.out.println("t1 已占有九尾妖狐");
try {
//停顿1000毫秒,另一个线程有足够的时间占有安妮
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("t1 试图占有安妮");
System.out.println("t1 等待中 。。。。");
synchronized (annie) {
System.out.println("do something");
}
}
}
};
t1.start();
Thread t2 = new Thread(){
public void run(){
//占有安妮
synchronized (annie) {
System.out.println("t2 已占有安妮");
try {
//停顿1000毫秒,另一个线程有足够的时间占有暂用九尾妖狐
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("t2 试图占有九尾妖狐");
System.out.println("t2 等待中 。。。。");
synchronized (ahri) {
System.out.println("do something");
}
}
}
};
t2.start();
}
}
借助tryLock 解决死锁问题
当多个线程按照不同顺序占用多个同步对象的时候,就有可能产生死锁现象。
死锁之所以会发生,就是因为synchronized 如果占用不到同步对象,就会苦苦的一直等待下去,借助tryLock的有限等待时间,解决死锁问题
package multiplethread;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestThread13 {
public static void main(String[] args) throws InterruptedException {
Lock lock_ahri = new ReentrantLock();
Lock lock_annie = new ReentrantLock();
Thread t1 = new Thread() {
public void run() {
// 占有九尾妖狐
boolean ahriLocked = false;
boolean annieLocked = false;
try {
ahriLocked = lock_ahri.tryLock(10, TimeUnit.SECONDS);
if (ahriLocked) {
System.out.println("t1 已占有九尾妖狐");
// 停顿1000秒,另一个线程有足够的时间占有安妮
Thread.sleep(1000);
System.out.println("t1 试图在10秒内占有安妮");
try {
annieLocked = lock_annie.tryLock(10, TimeUnit.SECONDS);
if (annieLocked)
System.out.println("t1 成功占有安妮,开始啪啪啪");
else{
System.out.println("t1 老是占用不了安妮,放弃");
}
} finally {
if (annieLocked){
System.out.println("t1 释放安妮");
lock_annie.unlock();
}
}
}
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
if (ahriLocked){
System.out.println("t1 释放九尾狐");
lock_ahri.unlock();
}
}
}
};
t1.start();
Thread.sleep(100);
Thread t2 = new Thread() {
public void run() {
boolean annieLocked = false;
boolean ahriLocked = false;
try {annieLocked = lock_annie.tryLock(10, TimeUnit.SECONDS);
if (annieLocked){
System.out.println("t2 已占有安妮");
// 停顿1000秒,另一个线程有足够的时间占有安妮
Thread.sleep(1000);
System.out.println("t2 试图在10秒内占有九尾妖狐");
try {
ahriLocked = lock_ahri.tryLock(10, TimeUnit.SECONDS);
if (ahriLocked)
System.out.println("t2 成功占有九尾妖狐,开始啪啪啪");
else{
System.out.println("t2 老是占用不了九尾妖狐,放弃");
}
}
finally {
if (ahriLocked){
System.out.println("t2 释放九尾狐");
lock_ahri.unlock();
}
}
}
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
if (annieLocked){
System.out.println("t2 释放安妮");
lock_annie.unlock();
}
}
}
};
t2.start();
}
}