熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

多線程中的死鎖舉例與分析

2022-06-13   來源: Java高級技術 

   一個特殊構造的程序

  考慮下面這個專門為說明多線程中的死鎖現象而構造的程序

  import javautilLinkedList;

  public class Stack {

  public static void main(String[] args) {

  final Stack stack = new Stack();

  new Thread(push) {

  @Override

  public void run() {

  for(int i = ; i < ; i++)

  {

  try {

  Threadsleep();

  } catch (InterruptedException e) {}

  stackpush(object + i);

  }

  }

  }start();

  new Thread(pop) {

  @Override

  public void run() {

  for(int i = ; i < ; i++)

  {

  try {

  Systemoutprintln(stackpop());

  } catch (Exception e) {}

  }

  }

  }start();

  }

  LinkedList<Object> list = new LinkedList<Object>();

  public synchronized void push(Object x) {

  Systemoutprintln(begin to push + x);

  synchronized (list) {

  listaddLast(x);

  notify();

  }

  Systemoutprintln(end to push + x);

  }

  public synchronized Object pop() throws Exception {

  Systemoutprintln(begin to pop);

  synchronized (list) {

  if (listsize() <= ) {

  wait();

  }

  return listremoveLast();

  }

  }

  }

  該程序構造了一個 Stack啟動了兩個線程一個線程向 Stack 中添加數據另外一個線程從 Stack 中取出數據並打印但是運行程序後就會發現程序輸出

  begin to pop

  begin to push object

  後在再也沒有後續輸出了

   Dump 並分析線程狀態

  啟動 jvisualvm 查看該程序線程的狀態將其 Dump就可以得到以下結果

  pop prio= tid=xb nid=x in Objectwait() [xeafxeafd] javalangThreadState: WAITING (on object monitor) at javalangObjectwait(Native Method)

   waiting on <xee> (a Stack)

  at javalangObjectwait(Objectjava:) at Stackpop(Stackjava:) locked <xee> (a javautilLinkedList)

   locked <xee> (a Stack)

  at Stack$run(Stackjava:)

  Locked ownable synchronizers:

   None

  push prio= tid=xb nid=x waiting for monitor entry [xefxefd] javalangThreadState: BLOCKED (on object monitor) at Stackpush(Stackjava:) waiting to lock <xee> (a javautilLinkedList)

   locked <xee> (a Stack)

  at Stack$run(Stackjava:)

  Locked ownable synchronizers:

   None

  可以看到pop 線程正在運行 wait(); 語句處於 WAITING 狀態同時該線程鎖住了 list 和 stack 對象push 線程處於 BLOCKED 狀態等待其他線程釋放 list 對象

   運行過程及死鎖原因分析

  

  步驟

  主程序

  pop 線程

  push 線程

  

  啟動

  

  創建 stack 對象

  

  創建 list 對象

  

  啟動

  

  啟動

  

  sleep ms

  

  調用 stackpop()

  

  鎖住 stack 對象

  

  打印 begin to pop

  

  鎖住 list 對象

  

  調用 stackwait()
(暫時釋放 stack 對象)

  

  鎖住 stack 對象

  

  打印 begin to push

  

  企圖鎖住 list 對象
(發現 list 已被其他線程鎖住)

  

  進入死鎖狀態

  原文地址 _zhongnan/blog/item/cfdel


From:http://tw.wingwit.com/Article/program/Java/gj/201311/27384.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.