漫画:如何证明sleep不释放锁,而wait释放锁?
wait 加鎖示例
public?class?WaitDemo?{private?static?Object?locker?=?new?Object();public?static?void?main(String[]?args)?throws?InterruptedException?{WaitDemo?waitDemo?=?new?WaitDemo();//?啟動新線程,防止主線程被休眠new?Thread(()?->?{try?{waitDemo.doWait();}?catch?(InterruptedException?e)?{e.printStackTrace();}}).start();Thread.sleep(200);?//?此行本身沒有意義,是為了確保?wait()?先執(zhí)行再執(zhí)行?notify()waitDemo.doNotify();}/***?執(zhí)行?wait()*/private?void?doWait()?throws?InterruptedException?{synchronized?(locker)?{System.out.println("wait?start.");locker.wait();System.out.println("wait?end.");}}/***?執(zhí)行?notify()*/private?void?doNotify()?{synchronized?(locker)?{System.out.println("notify?start.");locker.notify();System.out.println("notify?end.");}} }以上程序的執(zhí)行結(jié)果為:
wait start.?
notify start.?
notify end.?
wait end.
代碼解析
從上述代碼可以看出,我們給 wait()?和 notify()?兩個方法上了同一把鎖(locker),但在調(diào)用完 wait() 方法之后 locker?鎖就被釋放了,所以程序才能正常執(zhí)行 notify()?的代碼,因為是同一把鎖,如果不釋放鎖的話,是不會執(zhí)行 notify() 的代碼的,這一點也可以從打印的結(jié)果中證實(結(jié)果輸出順序),所以綜合以上情況來說 wait()?方法是釋放鎖的。
sleep 加鎖示例
public?class?WaitDemo?{private?static?Object?locker?=?new?Object();public?static?void?main(String[]?args)?throws?InterruptedException?{WaitDemo?waitDemo?=?new?WaitDemo();//?啟動新線程,防止主線程被休眠new?Thread(()?->?{synchronized?(locker)?{try?{System.out.println("sleep?start.");Thread.sleep(1000);System.out.println("sleep?end.");}?catch?(InterruptedException?e)?{e.printStackTrace();}}}).start();Thread.sleep(200);waitDemo.doNotify();}/***?執(zhí)行?notify()*/private?void?doNotify()?{synchronized?(locker)?{System.out.println("notify?start.");locker.notify();System.out.println("notify?end.");}} }以上程序的執(zhí)行結(jié)果為:
sleep start.?
sleep end.?
notify start.?
notify end.
代碼解析
從上述代碼可以看出 sleep(1000)?方法(行號:11)執(zhí)行之后,調(diào)用 notify()?方法并沒有獲取到 locker 鎖,從上述執(zhí)行結(jié)果中可以看出,而是執(zhí)行完 sleep(1000) 方法之后才執(zhí)行的 notify() 方法,因此可以證明調(diào)用 sleep()?方法并不會釋放鎖。
知識擴展
1.sleep 和 wait 有什么區(qū)別?
sleep 和 wait?幾乎是所有面試中必問的題,但想完全回答正確似乎沒那么簡單。
對于 sleep 和 wait 的區(qū)別,通常的回答是這樣的:
wait 必須搭配 synchronize 一起使用,而 sleep 不需要;
進入 wait 狀態(tài)的線程能夠被 notify 和 notifyAll 線程喚醒,而 sleep 狀態(tài)的線程不能被 notify 方法喚醒;
wait 通常有條件地執(zhí)行,線程會一直處于 wait 狀態(tài),直到某個條件變?yōu)檎?#xff0c;但是 sleep 僅僅讓你的線程進入睡眠狀態(tài);
wait 方法會釋放對象鎖,但 sleep 方法不會。
但上面的回答顯然遺漏了一個重要的區(qū)別,在調(diào)用 wait 方法之后,線程會變?yōu)?WATING?狀態(tài),而調(diào)用 sleep?方法之后,線程會變?yōu)?TIMED_WAITING?狀態(tài)。
2.wait 能不能在 static 方法中使用?為什么?
不能,因為 wait?方法是實例方法(非 static 方法),因此不能在 static 中使用,源碼如下:
public?final?void?wait()?throws?InterruptedException?{wait(0); }3.wait/notify 可以不搭配 synchronized 使用嗎?為什么?
不行,因為不搭配 synchronized?使用的話程序會報錯,如下圖所示:
更深層次的原因是因為不加 synchronized 的話會造成 Lost Wake-Up Problem,喚醒丟失的問題,詳情可見:https://juejin.im/post/5e6a4d8a6fb9a07cd80f36d1
總結(jié)
本文我們通過 synchronized 鎖定同一對象,來測試 wait?和 sleep?方法,再通過執(zhí)行結(jié)果的先后順序證明:wait?方法會釋放鎖,而 sleep?方法并不會。同時我們還講了幾個 wait 和 sleep 的常見面試問題,希望本文可以幫助到你。
漫畫:Integer 竟然有 4 種比較方法?
漫畫:對象是如何被找到的?句柄 OR 直接指針?
關(guān)注下方二維碼,每一天都有干貨!
總結(jié)
以上是生活随笔為你收集整理的漫画:如何证明sleep不释放锁,而wait释放锁?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你必须知道的session与cookie
- 下一篇: Chrome浏览器必装的扩展工具