Java中因join调用引发的两种死锁情形

最近做的一个项目使用Java编写,在调试中遇到两种因为调用join()引发的死锁情形,很隐蔽。记录于此。

1.线程join自身发生死锁

public class Starter {
        public static void main(String[] args) {
	         new DeadThread().start();
	}
}

class DeadThread {
	public DeadThread() {
		thread = new Thread(new RealThread());
	}
	public void start() {
		thread.start();
	}
	private Thread thread;
	private class RealThread implements Runnable{
		public void run() {
			System.out.println("Thread is starting...");
			try {
				thread.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("Thread is stopping...");
		}
	}
}

线程RealThread调用thread.join()本是想与另一个线程同步(示例代码中没有展示),但正如示例代码表现的那样,thread实际指向了它自身,这就形成了一种诡异的死锁情形:一个正在运行中的线程调用join()来等待自己结束

2.锁的维护不当

相比上面的情形,下面的情景则更为常见。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Starter {
	public static void main(String[] args) {
		DeadThread dt = new DeadThread();
		dt.start();
		dt.stop();
	}
}

class DeadThread {
	public DeadThread() {
		thread = new Thread(new RealThread());
		lock = new ReentrantLock();
	}
	public void start() {
		thread.start();
	}
	public void stop() {
		lock.lock();
		try {
			// do some real works...
			running = false;
			thread.join();        // (2)
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	private Thread thread;
	private Lock lock;
	private volatile boolean running = true;
	private class RealThread implements Runnable{
		public void run() {
			while (running) {     // (1)
				lock.lock();  // (3)
				try {
					// do some real works...
					System.out.println("Thread is running...");
				} finally {
					lock.unlock();
				}	
			}

		}
	}
}

上面的代码在大部分情况下都能正常工作,但是死锁的情形依然存在。线程以如下的顺序执行时,就出现了死锁:

<1>RealThread线程执行到(1)处,即while(running)执行完时,被DeadThread线程抢占

<2>DeadThread线程调用stop()函数,而此时的thread指向<1>中的RealThread线程,当stop()函数执行到(2)处,会等待RealThread的结束,放弃CPU

<3>RealThread线程恢复执行,此时因为DeadThread占有lock锁,所以RealThread会在(3)处等待线程DeadThread释放lock

在<3>执行完后,DeadThread线程和RealThread线程互相等待,便发生死锁。

    原文作者:java锁
    原文地址: https://blog.csdn.net/enjoysilence/article/details/9747271
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞