更新時間:2019-12-26 09:52:06 來源:動力節(jié)點 瀏覽3803次
一段時間沒有回顧多線程相關(guān)知識了,雖然工作中會用到一些多線程的內(nèi)容,但都偏向于基礎(chǔ),今天重讀多線程相關(guān)內(nèi)容,發(fā)現(xiàn)有些東西還是需要注意下。這些一般是面試高頻問題奧。
了解并發(fā)的內(nèi)幕是一個高級程序員不可缺少的課程
Java內(nèi)存模型
注意,Java內(nèi)存模型(JMM)和JVM運行時數(shù)據(jù)區(qū)不是同一個概念,還有一個概念是Java對象模型下次可以單獨拿出來說。
JMM都是圍繞著原子性,可見性,有序性來講的
JMM定義了JVM如何與計算機的內(nèi)存進行交互
線程對變量的所有操作都需要在工作內(nèi)存中完成,不可直接操作主內(nèi)存。
內(nèi)存間的交互操作:
Volatile
Volatile可以說是Java虛擬機內(nèi)提供的最輕量級同步機制,其只保證,可見性與有序性,不保證原子性。
可見性:當(dāng)一條線程修改了這個變量的值,新值對于其他線程來說是可以立刻得知的,另外兩個可以實現(xiàn)可見性的關(guān)鍵字:Synchronized和final
有序性:如果再本線程內(nèi)觀察,所有的操作都是有序的,如果再一個線程中觀察另外一個線程,那么所有的操作都是無序的。
Java與線程
并發(fā)不一定依賴多線程,如PHP中常見的多進程并發(fā)。Java的Thread類所有關(guān)鍵方法都是聲明為Native的,所以Java并沒有自己實現(xiàn)線程。
實現(xiàn)線程的三種方式:使用內(nèi)核線程實現(xiàn),使用用戶線程實現(xiàn),和使用用戶線程加更加輕量級進程實現(xiàn)。
內(nèi)核線程實現(xiàn)(KLT,Kernel-Level Thread)。程序一般不會直接使用內(nèi)核線程,而是使用內(nèi)核線程的一種高級接口,輕量級進程(LWP,Light Weight Process,LWP),先有內(nèi)核線程,才能有輕量級進程。
缺點:各種線程操作,如創(chuàng)建,析構(gòu),及同步需要進行系統(tǒng)調(diào)用,而系統(tǒng)調(diào)用的代價比較高,需要在用戶態(tài)和內(nèi)核態(tài)中來回切換。消耗內(nèi)核資源,一個系統(tǒng)支持輕量級的進程數(shù)量是有限制的。
用戶線程實現(xiàn),廣義上說,一個線程只要不是內(nèi)核線程,那就可以任務(wù)是用戶線程。用戶線程完全在用戶態(tài)完成,不用內(nèi)核的幫助,可以支持更大的線程數(shù)量。
缺點:沒有內(nèi)核支持,各種操作都比較復(fù)雜。現(xiàn)在基本棄用了。
用戶線程 + 輕量級進程,綜合兩者的有點,用戶進程與輕量級進程數(shù)量比是不定的。
線程調(diào)度
協(xié)同式調(diào)度:好處是實現(xiàn)簡單,切換操作對線程自己是可知的,沒有線程同步的問題,線程把自己的事情干完之后才進行線程切換。
缺點:如果程序編寫不穩(wěn)定,那么系統(tǒng)不可控制。一個進程堅持不讓出CPU執(zhí)行實現(xiàn),就會導(dǎo)致系統(tǒng)崩潰。
搶占式調(diào)度(Java默認(rèn)調(diào)度):每個線程由系統(tǒng)來分配執(zhí)行和弦,線程的切換不由線程來決定,當(dāng)一個進程出現(xiàn)問題,系統(tǒng)可以殺掉這個進程。
注意:并不是線程的優(yōu)先級越高,線程就一定會優(yōu)先執(zhí)行,只是說優(yōu)先級高的線程更可能被選擇到。
Java線程狀態(tài)轉(zhuǎn)換
貼一張圖,好好記:
線程安全的實現(xiàn)方法
互斥同步,加鎖,悲觀方案,保證共享數(shù)據(jù)同一時刻只有一個線程訪問。,互斥是因,同步是果。
非阻塞同步,CAS,樂觀方案,先進行操作,如果沒有其他線程也進行操作,那么就操作成功了,如果有其它線程也在操作共享數(shù)據(jù),那么再重試。
無同步方案,一般為純代碼,有一些特性,如不依賴堆上的公用系統(tǒng)資源
鎖優(yōu)化
自旋鎖與自適應(yīng)自旋
假如共享數(shù)據(jù)只會持續(xù)很短的一段時間,為了這段時間進行掛起和恢復(fù)線程并不值得,這時我們可以讓后面請求鎖的線程稍等一下,讓線程進行一個忙循環(huán)(自旋),這就是所謂的自旋鎖。
因為們有時不值得共享數(shù)據(jù)到底被鎖了多久,盲目的自旋可能導(dǎo)致性能的損失,JDK1.6之后,系統(tǒng)引入了自適應(yīng)的自旋,及在一次共享數(shù)據(jù)被鎖定時,加入系統(tǒng)多次獲得自旋鎖,系統(tǒng)可以允許線程自旋的次數(shù)更多時間更久一些。如果多次沒有獲得自旋鎖,那么系統(tǒng)下次可能會省略掉自旋鎖。
鎖消除
對一些不可能存在共享數(shù)據(jù)競爭的鎖進行消除。
鎖粗化
有時候多個操作都對同一個對象加鎖,頻繁的加鎖也會影響性能,那么系統(tǒng)就把鎖的同步范圍進行擴展。如StringBuffer()的多個append操作。
偏向鎖
可以理解為偏袒鎖,鎖會偏向于第一個獲得它的線程,如果接下來的執(zhí)行過程中,該鎖沒有被其他線程獲取,則持有偏向鎖的線程將永遠(yuǎn)不在需要進行同步。
以上就是動力節(jié)點Java培訓(xùn)機構(gòu)小編介紹的“Java高級程序員必備的內(nèi)容知識”的內(nèi)容,希望對大家有幫助,如有疑問,請在線咨詢,有專業(yè)老師隨時為你服務(wù)。
Java全套自學(xué)資料+視頻
Java自學(xué)視頻教程(免費學(xué)習(xí)):http://www.dabaquan.cn/video.html
Java技術(shù)教程:http://www.dabaquan.cn/tutorial/
相關(guān)內(nèi)容
相關(guān)閱讀