多線程喚醒問題
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運(yùn)行"?+?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運(yùn)行"?+?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運(yùn)行"+j+"次"); ????????????????} ????????????????flag?=?1; ????????????????this.notifyAll(); ????????????} ????????} ????} }
A線程先運(yùn)行10次,然后B線程運(yùn)行20次,然后C線程運(yùn)行30次,如此反復(fù)50次的代碼,為什么次c方法里要用this.notifyAll,而用this.notify就不行
2017-02-09
三個(gè)方法里至少有一個(gè)是notifyAll。假設(shè)三個(gè)都是notify(),當(dāng)方法c運(yùn)行完后,flag為1,此時(shí)如果a和b都已經(jīng)在Wait Set中,且隨機(jī)喚醒的是b,那么b隨機(jī)又進(jìn)入Wait set,c也進(jìn)入Wait set,此時(shí)三個(gè)線程全部進(jìn)入Wait set,造成了死鎖。
2020-12-13
哈哈? 確實(shí)??