天天看點

java多線程中死鎖情況的一個示例

 下面是死鎖情況的一個示例代碼

[java] view

plaincopy

java多線程中死鎖情況的一個示例
java多線程中死鎖情況的一個示例

package com.qust.demo.money;  

class a {  

    public synchronized void foo(b b) {  

        system.out.println(thread.currentthread().getname() + " 進入a的foo");  

        try {  

            thread.sleep(200);  

        } catch (interruptedexception ex) {  

            ex.printstacktrace();  

        }  

        system.out.println(thread.currentthread().getname() + " 試圖調用b的last");  

        b.last();  

    }  

    public synchronized void last() {  

        system.out.println("a的last()");  

}  

class b {  

    public synchronized void bar(a a) {  

        system.out.println(thread.currentthread().getname() + " 進入b的bar");  

        system.out.println(thread.currentthread().getname() + " 試圖調用a的last");  

        a.last();  

        system.out.println("b的last()");  

public class deadlock implements runnable {  

    a a = new a();  

    b b = new b();  

    public void init() {  

        thread.currentthread().setname("主線程");  

        system.out.println("進入主線程");  

        a.foo(b);  

    public void run() {  

        thread.currentthread().setname("副線程");  

        system.out.println("進入副線程");  

        b.bar(a);  

    public static void main(string[] args) {  

        deadlock dl = new deadlock();  

        new thread(dl).start();  

        dl.init();  

    下面是運作結果

[html] view

java多線程中死鎖情況的一個示例
java多線程中死鎖情況的一個示例

進入主線程  

進入副線程  

主線程 進入a的foo  

副線程 進入b的bar  

副線程 試圖調用a的last  

主線程 試圖調用b的last  

    我們看到,正常情況下,最後還應該列印出“a的last()”和"b的last()",但是因為線程死鎖的原因,是以程式一直在等待執行,沒能正常的執行下去。

    在上面的代碼裡面,為什麼會出現死鎖這種情況呢?我們來簡單分析一下。

    首先雖然副線程的start()是在主線程的init()之前,但是因為多線程開啟也需要一段時間,是以我們可以看到,是主線程的init()方法執行在前,然後在init()裡面調用了a.foo()。a類和b類中的方法都是同步方法,是以,a的對象和b的對象都是同步鎖。在進入a的foo()之前,線程會對a加鎖,然後線程睡眠200ms,這時候副線程調用b的bar(),同樣的會對b加鎖,然後睡眠200ms。這時候,主線程喚醒,試圖調用b的bar方法,因為是同步方法,是以需要對b加鎖,但是這時候b已經被副線程鎖住了,是以主線程就一直處于阻塞狀态。當副線程喚醒的時候,試圖調用a的同步方法,同樣需要對a加鎖,但是這時候主線程持有a的鎖,并處于阻塞狀态,是以副線程也不能向下執行,大家都在等着對方釋放鎖,是以出現了我們上面說的死鎖的情況。

    如果我們把a和b的last()的synchronized去掉,那麼程式在調用last()之前就不需要對對象進行加鎖,也就不會出現死鎖的情況。

    因為在工作中還沒有遇到這種情況,是以隻能拿這個執行個體程式講解了。