死鎖實(shí)現(xiàn)
public class DeathLockTest {
static Integer b = 100;
static Integer a = 0;
public static void main(String[] args) {
new Thread(() -> {
synchronized (a){
System.out.println(Thread.currentThread().getName() + ": i locked a");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b){
System.out.println(Thread.currentThread().getName() + ": i locked b");
}
}
},"thread-a").start();
new Thread(() -> {
synchronized (b){
System.out.println(Thread.currentThread().getName() + ": i locked b");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (a){
System.out.println(Thread.currentThread().getName() + ": i locked a");
}
}
},"thread-b").start();
}
}

死鎖結(jié)果
這里簡單的用了兩個線程去分別獲取到a的鎖和b的鎖,然后再獲取另外一個鎖的時候,就發(fā)現(xiàn)互相等待,互相不會釋放資源,導(dǎo)致死鎖的發(fā)生。死鎖在我們的項目中會導(dǎo)致很嚴(yán)重的后果,有多嚴(yán)重,碰到的人知道。
定義
死鎖是指兩個或兩個以上的進(jìn)程在執(zhí)行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去。此時稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱為死鎖進(jìn)程。[百度百科]
如何避免
1:獲取鎖的順序問題
如果我們在獲取兩個資源的時候,獲取的順序相同,都先獲取到a的鎖,然后再獲取到b的鎖,則在上述例子中避免了死鎖。
2:避免同時持有兩個資源的鎖
假設(shè)上面的例子中,thread-a獲取到a的鎖以后,對a的操作進(jìn)行完成以后再獲取b的鎖,那么,就可以解開這個死鎖,thread-b同理。
3:使用java.util.concurrent包中的相關(guān)方法改造
對上面的代碼進(jìn)行改造
public class DeathLockTest2 {
static Integer a = 0;
static Integer b = 100;
static Lock lock1 = new ReentrantLock();
static Lock lock2 = new ReentrantLock();
public static void main(String[] args) {
new Thread(()->{
try{
if(lock1.tryLock()){
System.out.println(Thread.currentThread().getName() + ": lock1 was locked");
a++;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(lock2.tryLock()){
System.out.println(Thread.currentThread().getName()+ " lock2 was locked");
b--;
}
System.out.println(Thread.currentThread().getName()+ "--> ++a :" + a + " , --b:" + b);
}
}finally {
lock1.unlock();
lock2.unlock();
}
},"thread-a").start();
new Thread(()->{
try {
if(lock2.tryLock()){
System.out.println(Thread.currentThread().getName()+ " lock2 was locked");
b--;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(lock1.tryLock()){
System.out.println(Thread.currentThread().getName() + ": lock1 was locked");
a++;
}
}
System.out.println(Thread.currentThread().getName()+ "--> ++a :" + a + " , --b:" + b);
}finally {
lock2.unlock();
lock1.unlock();
}
},"thread-b").start();
//定時器計時
new Timer().schedule(new TimerTask(){
@Override
public void run() {
System.out.println(String.valueOf(Calendar.getInstance().get(Calendar.SECOND)));
}
}, 1, 1000);
}
}
使用java.util.concurrent.locks.Lock.tryLock()方法,結(jié)果如下:

解鎖
程序在等待了5s左右的時候,線程自動結(jié)束運(yùn)行了,使用這種方式則不會使我們的線程出現(xiàn)完全死鎖,程序無法進(jìn)行的狀態(tài),在等待一定時間后,線程無法獲取到鎖,則自動放棄獲取鎖。
結(jié)束語:可能還有更好的解決辦法,歡迎大家留言指正探討,謝謝!