zoukankan      html  css  js  c++  java
  • 多线程中的死锁举例与分析(转)

    1. 一个特殊构造的程序
    考虑下面这个专门为说明多线程中的死锁现象而构造的程序:

    import java.util.LinkedList;
    
    public class Stack {
        public static void main(String[] args) {
            final Stack stack = new Stack();
            new Thread("push") {
                @Override
                public void run() {
                    for (int i = 0; i < 100; i++) {
                        try {
                            Thread.sleep(10);//to make the deadlock occur
                        } catch (InterruptedException e) {
                        }
                        stack.push("object " + i);
                    }
                }
            }.start();
            
            new Thread("pop") {
                @Override
                public void run() {
                    for (int i = 0; i < 100; i++) {
                        try {
                            System.out.println(stack.pop());
                        } catch (Exception e) {
                        }
                    }
                }
            }.start();
        }
    
        LinkedList<Object> list = new LinkedList<Object>();
    
        public synchronized void push(Object x) {
            System.out.println("begin to push " + x);
            synchronized (list) {
                list.addLast(x);
                notify();
            }
            System.out.println("end to push " + x);
        }
    
        public synchronized Object pop() throws Exception {
            System.out.println("begin to pop");
            synchronized (list) {
                if (list.size() <= 0) {
                    wait();
                }
                return list.removeLast();
            }
        }
        
    }

    该程序构造了一个 Stack,启动了两个线程。一个线程向 Stack 中添加数据,另外一个线程从 Stack 中取出数据并打印。
    但是运行程序后就会发现程序输出:

    begin to pop
    begin to push object 0

    后,在再也没有后续输出了。

    2. Dump 并分析线程状态
    启动 jvisualvm 查看该程序线程的状态,将其 Dump,就可以得到以下线程堆栈信息:

    "pop" prio=6 tid=0x00c00000 nid=0x2b0 in Object.wait() [0x00f9f000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x27f65648> (a loggerlock.Stack)
        at java.lang.Object.wait(Object.java:485)
        at loggerlock.Stack.pop(Stack.java:49)
        - locked <0x27f65658> (a java.util.LinkedList)
        - locked <0x27f65648> (a loggerlock.Stack)
        at loggerlock.Stack$2.run(Stack.java:26)
    
       Locked ownable synchronizers:
        - None
    
    "push" prio=6 tid=0x00bfec00 nid=0x14c8 waiting for monitor entry [0x00f4f000]
       java.lang.Thread.State: BLOCKED (on object monitor)
        at loggerlock.Stack.push(Stack.java:39)
        - waiting to lock <0x27f65658> (a java.util.LinkedList)
        - locked <0x27f65648> (a loggerlock.Stack)
        at loggerlock.Stack$1.run(Stack.java:16)
    
       Locked ownable synchronizers:
        - None

    可以看到,pop 线程正在运行 wait(); 语句,处于 WAITING 状态,同时,该线程锁住了 list 和 stack 对象。
    push 线程处于 BLOCKED 状态,等待其他线程释放 list 对象。


    3. 运行过程及死锁原因分析

    步骤

    主程序

    pop 线程

    push 线程

    1

    启动

       

    2

    创建 stack 对象

       

    3

    创建 list 对象

       

    4

     

    启动

     

    5

       

    启动

    6

       

    sleep 10ms

    7

     

    调用 stack.pop()

     

    8

     

    锁住 stack 对象

     

    9

     

    打印 "begin to pop"

     

    10

     

    锁住 list 对象

     

    11

     

    调用 stack.wait()
    (暂时释放 stack 对象)

     

    12

       

    锁住 stack 对象

    13

       

    打印 "begin to push 0"

    14

       

    企图锁住 list 对象
    (发现 list 已被其他线程锁住)

    15

    进入死锁状态

    http://www.educity.cn/it/sun/201004191051041573.htm

  • 相关阅读:
    深入浅出MFC——MFC六大关键技术仿真(二)
    错误:Invalid action class configuration that references an unknown class named [XXX]的解决
    错误:java.lang.NoClassDefFoundError: com/project/common/exception/ServiceException 的解决
    SQL查询语句优化的实用方法
    ueditor表格边框没有颜色的解决
    ueditor显示内容末尾有多余标记的解决
    form表单中enctype属性作用
    springMVC中@RequestParam和@RequestBody注解的用法
    错误:This function has none of DETERMINISTIC... 的解决
    如何区分内存类型及查看内存的兼容性
  • 原文地址:https://www.cnblogs.com/softidea/p/4243654.html
Copyright © 2011-2022 走看看