線程安全
- 經(jīng)常用來描繪一段代碼赎懦。指在并發(fā)的情況下分瘾,該代碼經(jīng)過多線程使用,線程的調(diào)度順序不影響任何結(jié)果具滴。這個時候使用多線程蚂维,我們只需要關(guān)注系統(tǒng)的內(nèi)存,CPU是不是夠用力图。反過來步绸,線程不安全就意味著線程的順序會影響最終結(jié)果掺逼。
- 如果你的代碼在多線程下執(zhí)行和在單線程下執(zhí)行永遠都能獲得一樣的結(jié)果,那么你的代碼就是線程安全的瓤介。
同步
Java中的同步指的是通過人為的控制和調(diào)度吕喘,保證共享資源的多線程訪問成為線程安全,來保證結(jié)果的準確刑桑。如簡單的加入synchronized關(guān)鍵字氯质。在保證結(jié)果準確的同時,提高性能祠斧,才是優(yōu)秀的程序闻察。線程安全的優(yōu)先級高于性能。
當線程被創(chuàng)建并啟動以后琢锋,它既不是一啟動就進入了執(zhí)行狀態(tài)辕漂,也不是一直處于執(zhí)行狀態(tài)。在線程的生命周期中吴超,它要經(jīng)過新建(New)钉嘹、就緒(Runnable)、運行(Running)鲸阻、阻塞(Blocked)和死亡(Dead)5種狀態(tài)跋涣。尤其是當線程啟動以后,它不可能一直"霸占"著CPU獨自運行鸟悴,所以CPU需要在多條線程之間切換陈辱,于是線程狀態(tài)也會多次在運行、阻塞之間切換
- 新建狀態(tài)细诸,當程序使用new關(guān)鍵字創(chuàng)建了一個線程之后性置,該線程就處于新建狀態(tài),此時僅由JVM為其分配內(nèi)存揍堰,并初始化其成員變量的值
- 就緒狀態(tài)鹏浅,當線程對象調(diào)用了start()方法之后嗅义,該線程處于就緒狀態(tài)。Java虛擬機會為其創(chuàng)建方法調(diào)用棧和程序計數(shù)器隐砸,等待調(diào)度運行
- 運行狀態(tài)之碗,如果處于就緒狀態(tài)的線程獲得了CPU,開始執(zhí)行run()方法的線程執(zhí)行體季希,則該線程處于運行狀態(tài)
- 阻塞狀態(tài)褪那,當處于運行狀態(tài)的線程失去所占用資源之后,便進入阻塞狀態(tài)
-
在線程的生命周期當中式塌,線程的各種狀態(tài)的轉(zhuǎn)換過程
image.png
-
同步隊列(鎖池):假設(shè)線程A已經(jīng)擁有了某個對象(注意:不是類)的鎖博敬,而其它的線程想要調(diào)用這個對象的某個synchronized方法(或者synchronized塊),由于這些線程在進入對象的synchronized方法之前必須先獲得該對象的鎖的擁有權(quán)峰尝,但是該對象的鎖目前正被線程A擁有偏窝,所以這些線程就進入了該對象的同步隊列(鎖池)中,這些線程狀態(tài)為Blocked武学。
等待隊列(等待池):假設(shè)一個線程A調(diào)用了某個對象的wait()方法祭往,線程A就會釋放該對象的鎖(因為wait()方法必須出現(xiàn)在synchronized中,這樣自然在執(zhí)行wait()方法之前線程A就已經(jīng)擁有了該對象的鎖)火窒,同時 線程A就進入到了該對象的等待隊列(等待池)中硼补,此時線程A狀態(tài)為Waiting。如果另外的一個線程調(diào)用了相同對象的notifyAll()方法熏矿,那么 處于該對象的等待池中的線程就會全部進入該對象的同步隊列(鎖池)中已骇,準備爭奪鎖的擁有權(quán)。如果另外的一個線程調(diào)用了相同對象的notify()方法票编,那么 僅僅有一個處于該對象的等待池中的線程(隨機)會進入該對象的同步隊列(鎖池)褪储。
守護線程與用戶線程
守護線程與用戶的區(qū)別在于:守護線程依賴于創(chuàng)建它的線程,而用戶線程不依賴栏妖。如果在main線程里創(chuàng)建一個守護線程乱豆,當main方法運行完畢以后,守護線程也會隨著消亡吊趾。而用戶線程則不會宛裕,用戶線程會一直運行到其運行完畢。在JVM中论泛,垃圾收集器就是守護線程揩尸。