电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

多线程中的死锁举例与分析


发布日期:2021/7/17
 

一个特殊构造的程序

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

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

上一篇:实现继承Thread创建多线程

下一篇:Robocode的线程与执行次序