線程的優(yōu)勢
如果使用得當(dāng)葵袭,線程可以有效地降低程序的開發(fā)锈颗、維護(hù)的成本,同時(shí)提升復(fù)雜應(yīng)用程序的性能胸嘁。線程可以降低代碼的復(fù)雜度桂塞,使代碼更容易編寫脸狸、閱讀和維護(hù)。在GUI應(yīng)用程序中,線程可以提高用戶界面的響應(yīng)靈敏度炊甲,在服務(wù)器應(yīng)用程序中泥彤,可以提升資源利用率以及系統(tǒng)吞吐率。
線程帶來的風(fēng)險(xiǎn)
線程安全性是非常復(fù)雜的卿啡,在沒有充分同步的情況下吟吝,多個(gè)線程中的操作順序是不可預(yù)測的,甚至?xí)a(chǎn)生奇怪的結(jié)果颈娜。
安全性問題
下面是一個(gè)非線程安全的數(shù)值序列生成器剑逃。在單線程環(huán)境下,這個(gè)類能正確工作官辽,但在多線程環(huán)境下則不能蛹磺。線程安全性是不可破壞的,安全性不僅對多線程程序很重要同仆,對于單線程程序同樣重要萤捆。
@NotThreadSafe
public class UnsafeSequence {
private int value;
public int getNextVal(){
return value++;
}
}
問題在于,如果執(zhí)行時(shí)機(jī)不對俗批,兩個(gè)線程調(diào)用getNextVal()
會得到相同的值俗或。這是一種常見的并發(fā)安全問題,稱為競態(tài)條件(Race Condition)岁忘。在多線程環(huán)境下辛慰,getNextVal()是否會返回唯一的值,要取決于運(yùn)行時(shí)對線程中操作的交替執(zhí)行方式干像。
把getNextVal()修改為同步方法帅腌,可以修復(fù)錯(cuò)誤。
@ThreadSafe
public class Sequence {
private int value;
public synchronized int getNextVal() {
return value++;
}
}
活躍性問題
活躍性問題關(guān)注于“某件正確的事情最終會發(fā)生”這個(gè)目標(biāo)麻汰∧欤活躍性問題包括死鎖、饑餓什乙,以及活鎖挽封。
性能問題
活躍性意味著某件正確的事情最終會發(fā)生,但卻不夠好臣镣,因?yàn)槲覀兛偸窍MM快發(fā)生辅愿。性能問題包括:服務(wù)時(shí)間過長、響應(yīng)不靈敏忆某、吞吐率過低点待、資源消耗過高或者可伸縮型較低等等。
在設(shè)計(jì)良好的并發(fā)應(yīng)用程序中弃舒,線程能提升性能癞埠,但是無論如何状原,線程總會帶來運(yùn)行時(shí)的開銷。當(dāng)線程調(diào)度器臨時(shí)掛起活躍線程并轉(zhuǎn)而運(yùn)行另一個(gè)線程時(shí)苗踪,就會頻繁地進(jìn)行上下文切換操作(Context Switch)颠区,CPU將花更多時(shí)間在線程調(diào)度而不是線程運(yùn)行上。當(dāng)線程共享數(shù)據(jù)時(shí)通铲,必須使用同步機(jī)制毕莱,這些機(jī)制往往會一直某些編譯器優(yōu)化,使內(nèi)存緩沖區(qū)中的數(shù)據(jù)無效颅夺,以及增加共享內(nèi)存總線的同步流量朋截。所有的這些因素都將帶來額外的性能開銷。