【深入理解java虚拟机v3】代码清单4-9 死锁代码样例

文章目录

简介

目的是介绍Jconsole查看死锁线程的状态

例子

public class ThreadDeadLockTestCase_2 {

	/**
	 * 线程死锁等待演示
	 */
	static class SynAddRunnalbe implements Runnable {
		int a, b;

		public SynAddRunnalbe(int a, int b) {
			this.a = a;
			this.b = b;
		}

		@Override
		public void run() {
			synchronized (Integer.valueOf(a)) {      //锁定A
				synchronized (Integer.valueOf(b)) {  //锁定B
					System.out.println(a + b);
				}
			}
		}
	}

	public static void main(String[] args) {
		for (int i = 0; i < 100; i++) {
			new Thread(new SynAddRunnalbe(1, 2)).start();
			new Thread(new SynAddRunnalbe(2, 1)).start();
		}
	}

}

JDK1.6环境运行,包括jconsole

这段代码开了200个线程去分别计算1+2以及2+1的值,理论上for循环都是可省略的,两个线程也可能会导致死锁,不过那样概率太小,需要尝试运行很多次才能看到死锁的效果。如果运气不是特别差的话,上面带for循环的版本最多运行两三次就会遇到线程死锁,程序无法结束。

造成死锁的根本原因是Integer.valueOf()方法出于减少对象创建次数和节省内存的考虑,会对数值为-128~127之间的Integer对象进行缓存 [2] ,如果valueOf()方法传入的参数在这个范围之内,就直接返回缓存中的对象。

《Java虚拟机规范》中明确要求缓存的默认值,实际值可以调整,具体取决于
java.lang.Integer.Integer-Cache.high参数的设置

也就是说代码中尽管调用了200次Integer.valueOf()方法,但一共只返回了两个不同的Integer对象。假如某个线程的两个synchronized块之间发生了一次线程切换,那就会出现线程A在等待被线程B持有的
Integer.valueOf(1),线程B又在等待被线程A持有的Integer.valueOf(2),结果大家都跑不下去的情况。

出现线程死锁之后,点击JConsole线程面板的“检测到死锁”按钮,将出现一个新的“死锁”页签,如下图所示。
在这里插入图片描述
在这里插入图片描述
上图中很清晰地显示,线程Thread-96在等待一个被线程Thread-67持有的Integer对象,而点击线程Thread-67则显示它也在等待一个被线程Thread-96持有的Integer对象,这样两个线程就互相卡住,除非牺牲其中一个,否则死锁无法释放。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值