在Java中,我們通過同步機制,來解決線程的安全問題。
方式一:同步代碼塊
synchronized(同步螢幕){
//需要被同步的代碼
}
1.操作共享資料的代碼,即為需要被同步的代碼。 -->不能包含代碼多了,也不能包含代碼少了。
2.共享資料:多個線程共同操作的變量。比如:ticket就是共享資料。
3.同步螢幕,俗稱:鎖。任何一個類的對象,都可以充當鎖。要求:多個線程必須要共用同一把鎖。也就是必須是同一個對象作為鎖。
4.在實作Runnable接口建立多線程的方式中,我們可以考慮使用this充當同步螢幕。
方式二:同步方法。
如果操作共享資料的代碼完整的聲明在一個方法中,我們不妨将此方法聲明同步的。
1. 同步方法仍然涉及到同步螢幕,隻是不需要我們顯式的聲明。
2. 非靜态的同步方法,同步螢幕是:this ,文法:private synchronized void method()
靜态的同步方法,同步螢幕是:目前類本身,也就是這個類所對應的Class對象,文法:private static synchronized void method()
優缺點:
同步的方式,解決了線程的安全問題。---好處
操作同步代碼時,隻能有一個線程參與,其他線程等待。相當于是一個單線程的過程,效率低。 ---局限性(但是我感覺要同步就必然是這樣的)
切記:
同步
範圍太小:沒鎖住所有有安全問題的代碼
同步範圍太大:不能充分發揮多線程的功能,相當于變成單線程執行
釋放鎖的操作
目前線程的同步方法、同步代碼塊執行結束。
目前線程在同步代碼塊、同步方法中遇到break、return終止了該代碼塊、 該方法的繼續執行。
目前線程在同步代碼塊、同步方法中出現了未處理的Error或Exception,導緻異常結束。
目前線程在同步代碼塊、同步方法中執行了線程對象的wait()方法,目前線程暫停,并釋放鎖。
不會釋放鎖的操作
線程執行同步代碼塊或同步方法時,程式調用Thread.sleep()、 Thread.yield()方法暫停目前線程的執行。
線程執行同步代碼塊時,其他線程調用了該線程的suspend()方法将該線程 挂起,該線程不會釋放鎖(同步螢幕)。
應盡量避免使用suspend()和resume()來控制線程。(過期的方法)