这节课我们来讲讲死锁 及其解决办法,这节课讲完我们的线程入门部分就讲完了
当然,这只是入个门而已,各位有兴趣的话可以去了解自学下juc
OK,废话不多说,写代码
死锁问题的产生:
public class DeadLockTeach { public static void main(String[] args) { Object goods = new Object(); Object money = new Object(); Thread thread1 = new Thread1(goods,money,"线程1"); Thread thread2 = new Thread2(goods,money,"线程2"); thread1.start(); thread2.start(); /** * 嗯? 怎么什么都不输出?而且程序并没有结束运行,为什么会这个样子? * * 大家设想一下,有两个人在进行交易,一个人手里有钱,一个人手里有货 * 有钱的那人喊"一手交货,一手交钱" * 有货的那人喊"一手交钱,一手交货" * 两人都希望对方先给自己,担忧不愿意先给对方 ,这样这场交易是不是就永无止境的停滞不前且无法结束? * * 这就是死锁: * 死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象, * 若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁线程。 * * 简单点说: * 就是现在有两个资源R1,R2 * 两个线程T1,T2 * T1锁着R1要R2,T2锁着R2要R1,但双方都不愿意主动释放锁,最后就造成了死锁 */ } static class Thread1 extends Thread{ Object goods; Object money; public Thread1(Object goods, Object money, String name) { this.goods = goods; this.money = money; setName(name); } @Override public void run() { while (true) { //一手交钱 synchronized (money) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (goods) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("一手交钱,一手交货"); } } } } } static class Thread2 extends Thread{ Object goods; Object money; public Thread2(Object goods, Object money, String name) { this.goods = goods; this.money = money; setName(name); } @Override public void run() { while (true) { //一手交货 synchronized (goods) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } //一手交钱 synchronized (money) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("一手交货,一手交钱"); } } } } } }
解决办法:
生产者-消费者模式 信号灯法
/** * 生产者-消费者模式 */ public class ProducerConsumerModel { /** * 大家设想一个场景: * 行人和机动车都要过马路, * 机动车过马路的时候人肯定不能走 * 人走的时候机动车必须停着 * 而控制是人走还是机动车走就需要一个红绿灯(信号灯) * 这就是信号灯法 */ public static void main(String[] args) { Movie movie = new Movie(); Actor actor = new Actor(movie); Audience audience = new Audience(movie); actor.setMovieName("《正义联盟》"); actor.start(); audience.start(); /** * ?????!!! * 为啥只有演员拍。观众不能看? * * 现在就是正常拍,正常看啦 */ } static class Movie{ public String name; //电影是否拍摄完成 public boolean finished; //拍摄 void make(String name) { this.name = name; finished = true; } public String getName() { return name; } //播放 void play() { System.out.println("电影" + name + "正在放映"); //放完了就拍新的 finished = false; } public boolean isFinished() { return finished; } } //演员 static class Actor extends Thread{ Movie movie; String movieName; public Actor(Movie movie){ this.movie = movie; } //用于被告知要拍哪部电影 public void setMovieName(String movieName) { this.movieName = movieName; } @Override public void run() { while (true) { synchronized (movie) { //演员来拍电影 if (movie.isFinished()) { try { //拍完了就等着,等观众老爷看完了再拍 movie.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { movie.notify(); } try { //要拍5秒 Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } movie.make(movieName); System.out.println(movie.getName() + "电影拍完啦"); //拍完电影也要放开锁 try { movie.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } //观众 static class Audience extends Thread{ Movie movie; public Audience(Movie movie) { this.movie = movie; } @Override public void run() { while (true) { synchronized (movie) { if (!movie.isFinished()) { //没拍完不让看,等着 try { movie.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { movie.notify(); } try { Thread.sleep(200); movie.play(); System.out.println(movie.getName() + "这部电影真好看"); //wait会释放锁,sleep不会释放锁 //看完电影就把锁放开 movie.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }