多線程喚醒問題
public?class?FlagWork?{ ????public?static?void?main(String[]?args)?{ ????????final?Business1?b1?=?new?Business1(); ????????new?Thread(new?Runnable()?{ ? ????????????@Override ????????????public?void?run()?{ ????????????????b1.a(); ????????????} ????????}).start(); ????????new?Thread(new?Runnable()?{ ? ????????????@Override ????????????public?void?run()?{ ????????????????b1.b(); ????????????} ????????}).start(); ????????new?Thread(new?Runnable()?{ ????????????? ????????????@Override ????????????public?void?run()?{ ????????????????b1.c(); ????????????} ????????}).start(); ????} } ? class?Business1?{ ????private?int?flag?=?1; ? ????public?void?a()?{ ????????for?(int?i?=?0;?i?<?50;?i++)?{ ????????????synchronized?(this)?{ ????????????????while?(flag?!=?1)?{ ????????????????????try?{ ????????????????????????this.wait(); ????????????????????}?catch?(InterruptedException?e)?{ ????????????????????????//?TODO?Auto-generated?catch?block ????????????????????????e.printStackTrace(); ????????????????????} ????????????????} ????????????????for?(int?j?=?1;?j?<=?10;?j++)?{ ????????????????????System.out.println("線程a運行"?+?j?+?"次"); ????????????????} ????????????????flag?=?2; ????????????????this.notify(); ????????????} ????????} ????} ? ????public?void?b()?{ ????????for?(int?i?=?0;?i?<?50;?i++)?{ ????????????synchronized?(this)?{ ????????????????while?(flag?!=?2)?{ ????????????????????try?{ ????????????????????????this.wait(); ????????????????????}?catch?(InterruptedException?e)?{ ????????????????????????//?TODO?Auto-generated?catch?block ????????????????????????e.printStackTrace(); ????????????????????} ????????????????} ????????????????for?(int?j?=?1;?j?<=?20;?j++)?{ ????????????????????System.out.println("線程b運行"?+?j?+?"次"); ????????????????} ????????????????flag?=?3; ????????????????this.notify(); ????????????} ????????} ????} ????public?void?c()?{ ????????for?(int?i?=?0;?i?<?50;?i++)?{ ????????????synchronized(this){ ????????????????while(flag!=3){ ????????????????????try?{ ????????????????????????this.wait(); ????????????????????}?catch?(InterruptedException?e)?{ ????????????????????????//?TODO?Auto-generated?catch?block ????????????????????????e.printStackTrace(); ????????????????????} ????????????????} ????????????????for?(int?j?=?1;?j?<=?30;?j++)?{ ????????????????????System.out.println("線程c運行"+j+"次"); ????????????????} ????????????????flag?=?1; ????????????????this.notifyAll(); ????????????} ????????} ????} }
A線程先運行10次,然后B線程運行20次,然后C線程運行30次,如此反復50次的代碼,為什么次c方法里要用this.notifyAll,而用this.notify就不行
2017-02-09
三個方法里至少有一個是notifyAll。假設三個都是notify(),當方法c運行完后,flag為1,此時如果a和b都已經在Wait Set中,且隨機喚醒的是b,那么b隨機又進入Wait set,c也進入Wait set,此時三個線程全部進入Wait set,造成了死鎖。
2020-12-13
哈哈? 確實??