java虛擬機(jī)-線程安全與鎖優(yōu)化

當(dāng)多個線程訪問一個對象時,如果不用考慮這些線程在運(yùn)行時環(huán)境下的調(diào)度和交替執(zhí)行,也不需要進(jìn)行額外的同步,或者在調(diào)用方法進(jìn)行任何其他的協(xié)調(diào)操作,調(diào)用這個對象的行為都可以獲得正確的結(jié)果,那這個對象是線程安全的。——Brain Goetz


一、java中的線程安全

多個線程之間存在共享數(shù)據(jù)競爭是線程安全解決問題的前提。
如果將線程安全歸為非真即假的二元選項(xiàng),按照線程安全的程度由強(qiáng)至弱,可以分為以下五類

  • 不可變
    被final修飾的數(shù)據(jù)類型一但被正確構(gòu)建出來之后就是不可變的。
    String, Long, Double等
  • 絕對線程安全
    javaAPI提供的標(biāo)榜自己是線程安全的類大多情況下不上絕對線程安全的。如Vector的使用,有時需要手動添加同步措施。
  • 相對線程安全
    調(diào)用端需要采取一些額外的同步措施,如Vector, HashTable,Collections的synchronizedCollection()方法包裝的集合等。

二、常見的線程安全實(shí)現(xiàn)的方法

1. 互斥同步

何為同步?
多個線程并發(fā)訪問共享數(shù)據(jù)時,保證共享數(shù)據(jù)在同一時刻只被一個線程使用。
何為互斥?
互斥是實(shí)現(xiàn)同步的手段,臨界區(qū),互斥量,信號量都是主要的互斥實(shí)現(xiàn)方式。因此互斥是因,同步是果?;コ馐欠椒?,同步是目的。
如何實(shí)現(xiàn)同步互斥?
(1)synchronized
該關(guān)鍵字經(jīng)過編譯后會在同步塊的前后分別形成moniterenter和monitorexit這兩個字節(jié)碼指令。

這兩個字節(jié)碼指令都需要一個reference類型的參數(shù)來指定要鎖和解鎖的對象。如果java程序中明確指明了這個對象參數(shù),那就是這個對象的reference。如果沒有明確指定,那就根據(jù)synchronized修飾的是實(shí)例方法還是類方法,去取對應(yīng)的對象實(shí)例貨class對象作為鎖對象。
執(zhí)行monitorenter時鎖計數(shù)器加1,執(zhí)行monitorexit時鎖計數(shù)減1,鎖計數(shù)器為0時就釋放鎖,如果獲取鎖失敗就阻塞等待,知道對象鎖被另外一個線程釋放。

(2)ReentrantLock
lock和unlock配合try/finally使用

synchronized和reentrantlock兩者都是可重入鎖。
何為可重入鎖?:一個線程或得了某對象鎖后,后續(xù)執(zhí)行該對象上的其他加鎖方法不會阻塞而會直接獲取鎖,即一個線程獲取鎖的時候不會自己把自己鎖死。 

(3)reentrantlock與synchronized的區(qū)別

  • reentrantlock等待可中斷
  • reentrantlock可以實(shí)現(xiàn)公平鎖
  • reentrantlock可以綁定多個condition

兩者性能并無多少差別,使用時以合適的場景和方便為主。

2. 無同步方案

(1)ThreadLocal
線程本地私有變量。是以map的形式存儲變量Key—Value。其中key為當(dāng)前變量,value為要存儲的值。用數(shù)組來存儲,本質(zhì)上是拉鏈法來解決hash沖突。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容