1. 程式人生 > >java兩種經典死鎖例子,Lock發生死鎖案列

java兩種經典死鎖例子,Lock發生死鎖案列

第一種synchronized方式死鎖:
執行緒thread1先獲取鎖locka,然後在同步塊裡巢狀競爭鎖lockb。而執行緒thread2先獲取鎖lockb,然後在同步塊裡巢狀競爭鎖locka
(此時已經被執行緒thread1擁有,而thread1在等待lockb,而lockb被thread2擁有,thread2在等待locka……無線迴圈)。
package com.app.test;

import org.apache.poi.util.SystemOutLogger;

/**
 * Created by lirong5 on 2016/5/24.
 */
public class SyncDeadLock{
    private static Object locka = new Object();
    private static Object lockb = new Object();

    public static void main(String[] args){
        new SyncDeadLock().deadLock();
    }

    private void deadLock(){
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (locka){
                    try{
                        System.out.println(Thread.currentThread().getName()+" get locka ing!");
                        Thread.sleep(500);
                        System.out.println(Thread.currentThread().getName()+" after sleep 500ms!");
                    }catch(Exception e){
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" need lockb!Just waiting!");
                    synchronized (lockb){
                        System.out.println(Thread.currentThread().getName()+" get lockb ing!");
                    }
                }
            }
        },"thread1");

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lockb){
                    try{
                        System.out.println(Thread.currentThread().getName()+" get lockb ing!");
                        Thread.sleep(500);
                        System.out.println(Thread.currentThread().getName()+" after sleep 500ms!");
                    }catch(Exception e){
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+" need locka! Just waiting!");
                    synchronized (locka){
                        System.out.println(Thread.currentThread().getName()+" get locka ing!");
                    }
                }
            }
        },"thread2");

        thread1.start();
        thread2.start();
    }
}

執行main方法之後控制檯列印內容如下:

thread1 get locka ing!
thread2 get lockb ing!
thread1 after sleep 500ms!
thread1 need lockb!Just waiting!
thread2 after sleep 500ms!
thread2 need locka! Just waiting!

thread1 need lockb!Just waiting!表明thread1執行緒進入死鎖等待lockb釋放。

thread2 need locka! Just waiting!  表明thread2執行緒進入死鎖等待locka釋放。 

第二種concurrent包Lock錯誤使用,導致死鎖:

lock.unlock();釋放鎖使用地方不規範,導致死鎖不能正常釋放!

package com.app.test;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by lirong5 on 2016/5/24.
 */
public class LockDeadDemo {

    public static void main(String[] args){
        final DeadLockBean deadLockBean = new DeadLockBean();
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    deadLockBean.productDeadLock();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            }
        },"threadA");
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(310);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    deadLockBean.productDeadLock();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            }
        },"threadB");
        threadA.start();
        threadB.start();
        try {
            System.out.println("main執行緒即將被join");
            threadA.join();
            threadB.join();
            System.out.println("main執行緒從join中恢復");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static class DeadLockBean{
        private Lock lock = new ReentrantLock();
        public void productDeadLock() throws Throwable {
            System.out.println(Thread.currentThread().getName() + "   進入了方法!");
            lock.lock();
            try{
                System.out.println(Thread.currentThread().getName() + "   已經執行了!");
                throw new Throwable("人為丟擲異常Throwable");//關鍵程式碼行1,
                //throw new Exception("人為丟擲異常Exception");//關鍵程式碼行2,不會死鎖,會在catch(Exception e中被捕獲),巢狀lock.unlock()並釋放
            }catch(Exception e){
                System.out.println(Thread.currentThread().getName()+"   發生異常catch!");
                //lock.unlock();//關鍵程式碼行3,不建議在這裡釋放,假如發生【關鍵程式碼行1】會產生死鎖
            }finally{
                System.out.println(Thread.currentThread().getName()+"   發生異常finally!");
                lock.unlock();//關鍵程式碼行4,無論發生何種異常,均會釋放鎖。
            }
            //lock.unlock();//關鍵程式碼行5,假如發生不能捕獲異常,將跳出方法體,不執行此處
            System.out.println(Thread.currentThread().getName() + "   tryCatch外釋放鎖!");
        }
    }
}