Java 线程死锁

概要:

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们将无法推进下去,此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。本实例模拟两个人就餐在等待一双筷子时引起的死锁现象。

| |目录

技术要点

    模拟等待筷子没法吃饭引起的死锁现象的技术要点如下:

  • 产生死锁的原因主要有:因为系统资源不足;进程运行推进的顺序不合适;资源分配不相等。如果系统的资源充足,进程的资源请求都能够得到满足,死锁出现的可以性就很低,否则就会因争夺有限资源而陷入死锁。另外,进程运行推进顺序与速度不同,也可能产生死锁。

  • 产生死锁的四个必要条件:一是互斥条件,一个资源每次只能被一个进程使用;二是请求与保持条件,一个进程因请求资源而阻塞时,对已获得的资源保持不放;三是不剥夺条件,进程已获得的资源,在未使用完之前,不能强行剥夺;四是循环等待条件,若干进程之间形成一种头尾相接的循环等待资源关系。这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

代码实现

package net.xsoftlab.baike;
public class TextDeadLock {
	static String[] chopsticks = new String[] { "筷子1", "筷子2" };
	static class OneThread extends Thread { // 静态内部类
		public void run() {
			synchronized (chopsticks[0]) { // 在同一时间只能有一个类访问
				System.out.println("甲拿起了" + chopsticks[0] + ",在等待另一"
						+ chopsticks[1]);
				try {
					Thread.sleep(100); // 线程休眠
				} catch (Exception e) { // 捕获异常
					System.out.println("线程休眠出错:" + e.getMessage());
				}
				synchronized (chopsticks[1]) {
					System.out.println("甲又拿起了" + chopsticks[1]);
				}
			}
		}
	}
	static class TwoThread extends Thread { // 静态内部类
		public void run() {
			synchronized (chopsticks[1]) {
				System.out.println("乙拿起了" + chopsticks[1] + ",在等待另一"
						+ chopsticks[0]);
				try {
					Thread.sleep(100); // 线程休眠
				} catch (Exception e) { // 捕获异常
					System.out.println("线程休眠出错:" + e.getMessage());
				}
				synchronized (chopsticks[0]) {
					System.out.println("乙又拿起了" + chopsticks[1]);
				}
			}
		}
	}
	static class DaemonThread extends Thread { // 静态守护线程类
		public DaemonThread() {
			this.setDaemon(true); // 线程设置守护
		}
		public void run() {
			while (true) {
				try {
					Thread.sleep(1000); // 线程休眠
				} catch (Exception e) { // 捕获异常
					System.out.println("线程休眠出错:" + e.getMessage());
				}
				System.out.println("守护线程:程序正在运行...");
			}
		}
	}
	public static void main(String[] args) { // java程序主入口处
		OneThread one = new OneThread(); // 实例化对象
		TwoThread two = new TwoThread();
		DaemonThread daemon = new DaemonThread();
		one.start(); // 启动线程
		two.start();
		daemon.start();
	}
}

程序解读

  1. TextDeadLock类创建静态字符串数组,用来存放所需的筷子。创建静态内部类OneThread继承Thread线程类,实现其run()方法。在run()方法中运用同步块synchronized()来实现在同一时间只能有一个线程访问。在其同步块中再使用同步块。甲在拿起“筷子1”时在等待“筷子2”。静态内部类TwoThread继承Thread线程类,实现其run()方法。在run()方法中运用同步块synchronized()方法使乙拿起“筷子2”在等待“筷子1”,这样就造成了死锁问题。

  2. 静态内部类DaemonThread类继承Thread线程类,在其构造方法中通过方法setDaemon()设置该类为守护线程类。在run()方法中根据标识为真进行循环,使线程在每1秒休眠。


评论关闭
评论 还能输入200
评论关闭
评论 还能输入200
  • 全部评论(0)
资料加载中...
已关注 , 取消