Java死锁检测

Java 5引入了ThreadMXBean-一个为线程提供各种监视方法的接口。...区别在于findDeadlockedThreads也可以检测到由所有者锁引起的死锁(java.util.concurrent),而findMonitorDeadlockedThreads只能检测到监视器锁(即同步块)

 

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

class Shared {
	synchronized void methodOne(Shared s) {
		Thread t = Thread.currentThread();

		System.out.println(t.getName() + "is executing methodOne...");

		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println(t.getName() + "is calling methodTwo...");

		s.methodTwo(this);

		System.out.println(t.getName() + "is finished executing methodOne...");
	}

	synchronized void methodTwo(Shared s) {
		Thread t = Thread.currentThread();

		System.out.println(t.getName() + "is executing methodTwo...");

		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println(t.getName() + "is calling methodOne...");

		s.methodOne(this);

		System.out.println(t.getName() + "is finished executing methodTwo...");
	}
}

public class ThreadsInJava {
	public static void main(String[] args) {
		final Shared s1 = new Shared();

		final Shared s2 = new Shared();

		Thread t1 = new Thread() {
			public void run() {
				s1.methodOne(s2);
			}
		};

		Thread t2 = new Thread() {
			@Override
			public void run() {
				s2.methodTwo(s1);
			}
		};

		t1.start();

		t2.start();

		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		ThreadMXBean bean = ManagementFactory.getThreadMXBean();

		long ids[] = bean.findMonitorDeadlockedThreads();

		if (ids != null) {
			ThreadInfo threadInfo[] = bean.getThreadInfo(ids);

			for (ThreadInfo threadInfo1 : threadInfo) {
				System.out.println("ID of deadlocked thread : " + threadInfo1.getThreadId()); // Prints the ID of
																								// deadlocked thread

				System.out.println("name of deadlocked thread : " + threadInfo1.getThreadName()); // Prints the name of
																									// deadlocked thread

				System.out.println("object : " + threadInfo1.getLockName()); // Prints the string representation of an
																				// object for
				// which thread has entered into deadlock.

				System.out.println("ID of thread which currently owns : " + threadInfo1.getLockOwnerId()); // Prints the
																											// ID of
																											// thread
																											// which
																											// currently
																											// owns the
				// object lock

				System.out.println("name of thread which currently owns : " + threadInfo1.getLockOwnerName()); // Prints
																												// name
																												// of
																												// the
																												// thread
																												// which
																												// currently
																												// owns
				// the object lock.
			}
		} else {
			System.out.println("No Deadlocked Threads");
		}
	}
}
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

public class ThreadDeadlock {

	public static void main(String[] args) throws InterruptedException {
		Object obj1 = new Object();
		Object obj2 = new Object();
		Object obj3 = new Object();

		Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
		Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
		Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");

		t1.start();
		Thread.sleep(5000);
		t2.start();
		Thread.sleep(5000);
		t3.start();
		
		try {
			Thread.sleep(60000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		ThreadMXBean bean = ManagementFactory.getThreadMXBean();

		long ids[] = bean.findMonitorDeadlockedThreads();

		if (ids != null) {
			ThreadInfo threadInfo[] = bean.getThreadInfo(ids);

			for (ThreadInfo threadInfo1 : threadInfo) {
				System.out.println("ID of deadlocked thread : " + threadInfo1.getThreadId()); // Prints the ID of
																								// deadlocked thread

				System.out.println("name of deadlocked thread : " + threadInfo1.getThreadName()); // Prints the name of
																									// deadlocked thread

				System.out.println("object : " + threadInfo1.getLockName()); // Prints the string representation of an
																				// object for
				// which thread has entered into deadlock.

				System.out.println("ID of thread which currently owns : " + threadInfo1.getLockOwnerId()); // Prints the
																											// ID of
																											// thread
																											// which
																											// currently
																											// owns the
				// object lock

				System.out.println("name of thread which currently owns : " + threadInfo1.getLockOwnerName()); // Prints
																												// name
																												// of
																												// the
																												// thread
																												// which
																												// currently
																												// owns
				// the object lock.
			}
		} else {
			System.out.println("No Deadlocked Threads");
		}
		

	}

}

class SyncThread implements Runnable {
	private Object obj1;
	private Object obj2;

	public SyncThread(Object o1, Object o2) {
		this.obj1 = o1;
		this.obj2 = o2;
	}

	@Override
	public void run() {
		String name = Thread.currentThread().getName();
		System.out.println(name + " acquiring lock on " + obj1);
		synchronized (obj1) {
			System.out.println(name + " acquired lock on " + obj1);
			work();
			System.out.println(name + " acquiring lock on " + obj2);
			synchronized (obj2) {
				System.out.println(name + " acquired lock on " + obj2);
				work();
			}
			System.out.println(name + " released lock on " + obj2);
		}
		System.out.println(name + " released lock on " + obj1);
		System.out.println(name + " finished execution.");
	}

	private void work() {
		try {
			Thread.sleep(30000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
package com.example.thread.deadlock.lock;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class BankAccount {
	double balance;
	final int id;
	final Lock lock = new ReentrantLock();

	BankAccount(int id, double balance) {
		this.id = id;
		this.balance = balance;
	}

	void withdraw(double amount) {
		// Wait to simulate io like database access ...
		try {
			Thread.sleep(10l);
		} catch (InterruptedException e) {
		}
		balance -= amount;
	}

	void deposit(double amount) {
		// Wait to simulate io like database access ...
		try {
			Thread.sleep(10l);
		} catch (InterruptedException e) {
		}
		balance += amount;
	}

	static void transfer(BankAccount from, BankAccount to, double amount) {
		from.lock.lock();
		from.withdraw(amount);
		to.lock.lock();
		to.deposit(amount);
		to.lock.unlock();
		from.lock.unlock();
	}

	public static void main(String[] args) {
		final BankAccount fooAccount = new BankAccount(1, 100d);
		final BankAccount barAccount = new BankAccount(2, 100d);

		new Thread() {
			public void run() {
				System.out.println(this.getId()+this.getName()+":"+fooAccount.balance);
				System.out.println(this.getId()+this.getName()+":"+barAccount.balance);
				BankAccount.transfer(fooAccount, barAccount, 10d);
				System.out.println(this.getId()+this.getName()+":"+fooAccount.balance);
				System.out.println(this.getId()+this.getName()+":"+barAccount.balance);
			}
		}.start();

		new Thread() {
			public void run() {
				System.out.println(this.getId() + this.getName() + ":" + fooAccount.balance);
				System.out.println(this.getId() + this.getName() + ":" + barAccount.balance);
				BankAccount.transfer(barAccount, fooAccount, 10d);
				System.out.println(this.getId() + this.getName() + ":" + fooAccount.balance);
				System.out.println(this.getId() + this.getName() + ":" + barAccount.balance);
			}
		}.start();
		
		
		try {
			Thread.sleep(60000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		ThreadMXBean bean = ManagementFactory.getThreadMXBean();

		long ids[] = bean.findDeadlockedThreads();

		if (ids != null) {
			ThreadInfo threadInfo[] = bean.getThreadInfo(ids);

			for (ThreadInfo threadInfo1 : threadInfo) {
				System.out.println("ID of deadlocked thread : " + threadInfo1.getThreadId()); // Prints the ID of
																								// deadlocked thread

				System.out.println("name of deadlocked thread : " + threadInfo1.getThreadName()); // Prints the name of
																									// deadlocked thread

				System.out.println("object : " + threadInfo1.getLockName()); // Prints the string representation of an
																				// object for
				// which thread has entered into deadlock.

				System.out.println("ID of thread which currently owns : " + threadInfo1.getLockOwnerId()); // Prints the
																											// ID of
																											// thread
																											// which
																											// currently
																											// owns the
				// object lock

				System.out.println("name of thread which currently owns : " + threadInfo1.getLockOwnerName()); // Prints
																												// name
																												// of
																												// the
																												// thread
																												// which
																												// currently
																												// owns
				// the object lock.
			}
		} else {
			System.out.println("No Deadlocked Threads");
		}
		

	}
}

 

 

 Java级别监视器死锁曾经很难找到。然后出现了JDK 1.4,并在CTRL + Break中显示了它们。在JDK 5中,我们看到了ThreadMXBean的添加,这使得可以连续监视应用程序中的死锁。但是,局限性在于ThreadMXBean仅适用于同步块,而不适用于新的java.util.concurrent机制。在此时事通讯中,我们重新审视了死锁检测器,并显示了需要进行哪些更改才能使其在JDK 6下工作。此外,我们还了解了什么是异步异常,以及如何将其发布到另一个线程。

第93号通讯中,我介绍了一个可自动检测线程死锁的类。Bruce Eckel指出,此机制仅适用于监视器 锁(即同步),而不适用于java.util.concurrent 拥有的锁。

在Java 6(测试版2)中,发现了监视器锁和拥有锁的死锁 。但是,需要修改死锁检测器,以获取已死锁的 拥有的锁。

在Java 5中,ThreadMXBean仅具有findMonitorDeadlockedThreads()方法,该方法发现了由synchronized关键字引起的死锁。现在,我们还有findDeadlockedThreads()Java虚拟机支持监视可拥有的同步器使用情况时启用的方法。(即新锁或相关构造)

 

如果您使用的是Java 5,则可以findMonitorDeadlockedThreads()在ThreadMXBean上调用方法,可以通过调用来获得java.lang.management.ManagementFactory.getThreadMXBean()。这将发现仅由对象监视器引起的死锁。在Java 6上findDeadlockedThreads(),还会发现“拥有的同步器(例如ReentrandLockReentrantReadWriteLock)引起的死锁。

请注意,调用这些方法可能会很昂贵,因此应仅将它们用于故障排除。

 

从Java 1.8开始,您可以通过jcmd在终端上使用命令轻松找到程序是否出现死锁。

  1. jcmd在您的终端上运行:它列出了所有使用Java的程序(PID和名称)。
  2. 现在,运行jcmd <PID> Thread.print:这将在控制台上打印线程转储,并且在程序出现死锁时也将打印。

您可以使用jcmd命令列出的更多选项 来分析Java程序jcmd <PID> help

 

 

Java可以检测死锁(尽管不是在运行时,它仍然可以诊断和报告死锁)。

例如,当使用略微修改的'Saurabh M. Chande'代码波纹管时(将其更改为Java,并添加了一些时间以确保每次运行都被锁定)。一旦运行它,它将陷入僵局,如果您键入:

kill -3 PID   # where 'PID' is the Linux process ID

它将生成一个堆栈转储,其中将包含以下信息:

Found one Java-level deadlock:
=============================
"Thread-0":
     waiting to lock monitor 0x08081670 (object 0x7f61ddb8, a Deadlock$A),
     which is held by "main"
"main":
      waiting to lock monitor 0x080809f0 (object 0x7f61f3b0, a Deadlock$B),
      which is held by "Thread-0"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值