JAVA多线程死锁

Java多线程中常需对同一资源访问进行限制,有sychronized等多种同步机制。但一个线程获取多个资源锁时易发生死锁,如示例中thread1和thread2休眠后获取锁的情况。可使用jps查看进程,jstack获取堆内存快照,还可用Lock的tryLock()方法避免死锁。

   ava多线程中经常需要对同一资源的访问进行限制。实现这种同步方式的机制有很多种。如:sychronized,Semaphore,ReentrantLock。

     但是针对一个线程需要获取多个资源的锁的时候 ,容易发生死锁的情况。如

package com.winston.thread.deadlock;

/**
 * 
 * @Description: 线程死锁
 *
 * @version: v1.0.0
 * @author: Winston
 * @date: 2018年8月28日 下午3:47:32
 */
public class TestDeadLock {

	public static void main(String[] args) {
		String lock1 = "aa";
		String lock2 = "bb";
		Thread thread1 = new Thread(new MyThread1(lock1, lock2));
		Thread thread2 = new Thread(new MyThread1(lock2, lock1));
		thread1.setName("thread1");
		thread2.setName("thread2");
		thread1.start();
		thread2.start();
	}

}

class MyThread1 implements Runnable {

	private String lock1;

	private String lock2;

	public MyThread1(String lock1, String lock2) {
		this.lock1 = lock1;
		this.lock2 = lock2;
	}

	@Override
	public void run() {

		synchronized (lock1) {
			System.out.println(Thread.currentThread().getName() + "获得:" + lock1);
			try {
				Thread.sleep(3 * 1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "等待:" + lock2);
			synchronized (lock2) {
				System.out.println(Thread.currentThread().getName() + "获得:" + lock2);
			}
		}

	}

}

本例中thread1获得:aa对象的锁,然后休眠了3秒钟。并且此间thread2获得:bb对象的锁。也休眠了3秒钟。当两个线程休眠结束的时候再接着获取第二个对象锁。对于thread1等待aa对象锁,thread2等待bb对象锁的时候 就发生了死锁。

       使用jps工具查看机器上运行的java进程。(当本地启动多个Tomcat的时候 使用jps会只打印出Tomcat的启动类名,无法对应进程号和具体应用。使用jps -lv会打印应用的完整路径名和传给jvm的参数。linux 上面可以使用  ps -aux|grep java)

C:\Users\Winston>jps -lv
10384  -Dosgi.requiredJavaVersion=1.8 -Dosgi.instance.area.default=@user.home/eclipse-workspace -XX:+UseG1GC -XX:+UseStringDeduplication -Dosgi.requiredJavaVersion=1.8 -Xms256m -Xmx1024m
7712  -Dosgi.requiredJavaVersion=1.8 -Dosgi.instance.area.default=@user.home/eclipse-workspace -XX:+UseG1GC -XX:+UseStringDeduplication -Dosgi.requiredJavaVersion=1.8 -Xms256m -Xmx1024m
47268 sun.tools.jps.Jps -Dapplication.home=C:\Program Files\Java\jdk1.8.0_152 -Xms8m
20776 com.winston.thread.deadlock.TestDeadLock -Dfile.encoding=UTF-8

 使用jstack获取堆内存快照 用法:jstack pid

C:\Users\Winston>jstack 20776
2018-08-28 16:16:37
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.79-b02 mixed mode):

"DestroyJavaVM" prio=6 tid=0x0000000002bae000 nid=0x290 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"thread2" prio=6 tid=0x000000000d363000 nid=0x55e4 waiting for monitor entry [0x000000000d9bf000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.winston.thread.deadlock.MyThread1.run(TestDeadLock.java:52)
        - waiting to lock <0x00000007d63d88a8> (a java.lang.String)
        - locked <0x00000007d63d88d8> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:745)

"thread1" prio=6 tid=0x000000000d360800 nid=0x3314 waiting for monitor entry [0x000000000d8be000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.winston.thread.deadlock.MyThread1.run(TestDeadLock.java:52)
        - waiting to lock <0x00000007d63d88d8> (a java.lang.String)
        - locked <0x00000007d63d88a8> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:745)

"Service Thread" daemon prio=6 tid=0x000000000b450000 nid=0x5394 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" daemon prio=10 tid=0x000000000b44c800 nid=0x51c0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" daemon prio=10 tid=0x000000000b445000 nid=0x51fc waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Attach Listener" daemon prio=10 tid=0x000000000b444000 nid=0x500c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x000000000b443000 nid=0x3438 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=8 tid=0x000000000301b000 nid=0x54ac in Object.wait() [0x000000000cdbf000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000007d6284858> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
        - locked <0x00000007d6284858> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" daemon prio=10 tid=0x000000000b407000 nid=0x5154 in Object.wait() [0x000000000ccbe000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000007d6284470> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:503)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
        - locked <0x00000007d6284470> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=10 tid=0x000000000b403000 nid=0x1404 runnable

"GC task thread#0 (ParallelGC)" prio=6 tid=0x0000000002f46800 nid=0x42a0 runnable

"GC task thread#1 (ParallelGC)" prio=6 tid=0x0000000002f49800 nid=0x50c8 runnable

"GC task thread#2 (ParallelGC)" prio=6 tid=0x0000000002f4b000 nid=0x51b4 runnable

"GC task thread#3 (ParallelGC)" prio=6 tid=0x0000000002f4c800 nid=0x2218 runnable

"GC task thread#4 (ParallelGC)" prio=6 tid=0x0000000002f4f000 nid=0x15c4 runnable

"GC task thread#5 (ParallelGC)" prio=6 tid=0x0000000002f50800 nid=0x40fc runnable

"VM Periodic Task Thread" prio=10 tid=0x000000000d2c8800 nid=0x41d4 waiting on condition

JNI global references: 108


Found one Java-level deadlock:
=============================
"thread2":
  waiting to lock monitor 0x000000000301ab78 (object 0x00000007d63d88a8, a java.lang.String),
  which is held by "thread1"
"thread1":
  waiting to lock monitor 0x0000000003019838 (object 0x00000007d63d88d8, a java.lang.String),
  which is held by "thread2"

Java stack information for the threads listed above:
===================================================
"thread2":
        at com.winston.thread.deadlock.MyThread1.run(TestDeadLock.java:52)
        - waiting to lock <0x00000007d63d88a8> (a java.lang.String)
        - locked <0x00000007d63d88d8> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:745)
"thread1":
        at com.winston.thread.deadlock.MyThread1.run(TestDeadLock.java:52)
        - waiting to lock <0x00000007d63d88d8> (a java.lang.String)
        - locked <0x00000007d63d88a8> (a java.lang.String)
        at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.


C:\Users\Winston>

thread2

        - waiting to lock <0x00000007d63d88a8> (a java.lang.String)
        - locked <0x00000007d63d88d8> (a java.lang.String)

thread1

        - waiting to lock <0x00000007d63d88d8> (a java.lang.String)
        - locked <0x00000007d63d88a8> (a java.lang.String)

线程thread2 等待的0x00000007d63d88a8被thread1  locked  。

 

其实工作中肯定不会编写以上代码。一般产生死锁的情况,都是因为程序缺陷导致的。

使用Lock的tryLock()方法也可以避免死锁的情况。

boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值