詳細(xì)介紹Java中的各種鎖
一、一張圖了解21種鎖
二、樂(lè)觀鎖
應(yīng)用 CAS 思想 一種樂(lè)觀思想,假定當(dāng)前環(huán)境是讀多寫(xiě)少,遇到并發(fā)寫(xiě)的概率比較低,讀數(shù)據(jù)時(shí)認(rèn)為別的線程不會(huì)正在進(jìn)行修改 實(shí)現(xiàn) 寫(xiě)數(shù)據(jù)時(shí),判斷當(dāng)前 與期望值是否相同,如果相同則進(jìn)行更新(更新期間加鎖,保證是原子性的)
三、悲觀鎖
應(yīng)用 synchronized、vector、hashtable 思想: 一種悲觀思想 ** ,即認(rèn)為寫(xiě)多讀少,遇到并發(fā)寫(xiě)的可能性高 實(shí)現(xiàn) 每次讀寫(xiě)數(shù)據(jù)都會(huì)認(rèn)為其他線程會(huì)修改,所以每次讀寫(xiě)數(shù)據(jù)時(shí)都會(huì)上鎖 缺點(diǎn) 他線程想要讀寫(xiě)這個(gè)數(shù)據(jù)時(shí),會(huì)被這個(gè)線程block,直到這個(gè)線程釋放鎖然后其他線程獲取到鎖
四、自旋鎖
應(yīng)用 CAS 實(shí)現(xiàn) 為了讓線程等待,我們只須讓線程執(zhí)行一個(gè)忙循環(huán) 優(yōu)點(diǎn) 避免了線程切換的開(kāi)銷(xiāo),掛起線程和恢復(fù)線程的操作都需要轉(zhuǎn)入內(nèi)核態(tài)中完成,這些操作給Java虛擬機(jī)的并發(fā)性能帶來(lái)了很大的壓力 缺點(diǎn) 占用處理器的時(shí)間,如果占用的時(shí)間很長(zhǎng),會(huì)白白消耗處理器資源,而不會(huì)做任何有價(jià)值的工作,帶來(lái)性能的浪費(fèi) 改進(jìn) 自旋等待的時(shí)間必須有一定的限度,如果自旋超過(guò)了限定的次數(shù)仍然沒(méi)有成功獲得鎖,就應(yīng)當(dāng)使用傳統(tǒng)的方式去掛起線程 jvm調(diào)優(yōu) -XX:PreBlockSpin 設(shè)置固定失敗次數(shù) 自適應(yīng)自旋 前一次在同一個(gè)鎖上的自旋時(shí)間及鎖的擁有者的狀態(tài)來(lái)決定的,通過(guò)系統(tǒng)監(jiān)控進(jìn)行調(diào)整
五、悲觀鎖
應(yīng)用 synchronized、vector、hashtable 思想: 一種悲觀思想 ** ,即認(rèn)為寫(xiě)多讀少,遇到并發(fā)寫(xiě)的可能性高 實(shí)現(xiàn) 每次讀寫(xiě)數(shù)據(jù)都會(huì)認(rèn)為其他線程會(huì)修改,所以每次讀寫(xiě)數(shù)據(jù)時(shí)都會(huì)上鎖 缺點(diǎn) 他線程想要讀寫(xiě)這個(gè)數(shù)據(jù)時(shí),會(huì)被這個(gè)線程block,直到這個(gè)線程釋放鎖然后其他線程獲取到鎖
六、可重入鎖(遞歸鎖)
應(yīng)用 synchronized、Reentrantlock、Lock 思想: 任意線程在獲取到鎖之后能夠再次獲取該鎖而不會(huì)被鎖所阻塞 實(shí)現(xiàn) 通過(guò)組合自定義同步器來(lái)實(shí)現(xiàn)鎖的獲取與釋放 獲取鎖:識(shí)別獲取鎖的線程是否為當(dāng)前占據(jù)鎖的線程 ,如果是,則再次成功獲,。獲取鎖后,進(jìn)行計(jì)數(shù)自增 釋放鎖:釋放鎖時(shí),進(jìn)行計(jì)數(shù)自減 優(yōu)點(diǎn): 避免死鎖 缺點(diǎn) 他線程想要讀寫(xiě)這個(gè)數(shù)據(jù)時(shí),會(huì)被這個(gè)線程block,直到這個(gè)線程釋放鎖然后其他線程獲取到鎖
七、讀寫(xiě)鎖
應(yīng)用 ReentrantReadWriteLock,CopyOnWriteArrayList、CopyOnWriteArraySet 思想 讀寫(xiě)分離 實(shí)現(xiàn) Java 提供了讀寫(xiě)鎖,在讀的地方使用讀鎖,在寫(xiě)的地方使用寫(xiě)鎖 讀鎖: 允許多個(gè)線程獲取讀鎖,同時(shí)訪問(wèn)同一個(gè) 寫(xiě)鎖: 只允許一個(gè)線程獲取寫(xiě)鎖,不允許同時(shí)訪問(wèn)同一個(gè)資源 優(yōu)點(diǎn): 避免死鎖 缺點(diǎn) 他線程想要讀寫(xiě)這個(gè)數(shù)據(jù)時(shí),會(huì)被這個(gè)線程block,直到這個(gè)線程釋放鎖然后其他線程獲取到鎖
八、公平鎖
應(yīng)用 Reentrantlock(true) 思想 多個(gè)線程按照申請(qǐng)鎖的順序來(lái)獲取鎖 實(shí)現(xiàn) 在并發(fā)環(huán)境中,每個(gè)線程會(huì)先查看此鎖維護(hù)的等待隊(duì)列,如果當(dāng)前等待隊(duì)列為空,則占有鎖,如果等待隊(duì)列不為空,則加入到等待隊(duì)列的末尾, 按照FIFO的原則從 隊(duì)列中拿到線程,然后占有鎖
九、非公平鎖
應(yīng)用 synchronized、reentrantlock(false) 思想 線程嘗試獲取鎖,如果獲取不到,則再采用公平鎖的方式 實(shí)現(xiàn) 多個(gè)線程獲取鎖的順序,不是按照先到先得的順序,有可能后申請(qǐng)鎖的線程比先申請(qǐng)的線程優(yōu)先獲取鎖
十、共享鎖
應(yīng)用 ReentrantReadWriteLock中讀鎖 思想 可以有多個(gè)線程獲取讀鎖,以共享的方式持有鎖
十一、獨(dú)鎖
應(yīng)用 synchronized、vector、hashtable、ReentrantReadWriteLock中寫(xiě)鎖 思想 是一種思想: 只能有一個(gè)線程獲取鎖,以獨(dú)占的方式持有鎖
十二、重量級(jí)鎖
應(yīng)用 synchronized 思想 synchronized是通過(guò)對(duì)象內(nèi)部的一個(gè)叫做監(jiān)視器鎖(monitor)來(lái)實(shí)現(xiàn)的,監(jiān)視器鎖本身依賴(lài)底層的操作系統(tǒng)的 Mutex Lock來(lái)實(shí)現(xiàn)。 缺點(diǎn) 操作系統(tǒng)實(shí)現(xiàn)線程的切換需要從用戶(hù)態(tài)切換到核心態(tài),成本非常高。這種依賴(lài)于操作系統(tǒng) Mutex Lock來(lái)實(shí)現(xiàn)的鎖稱(chēng)為重量級(jí)鎖。 改進(jìn) 為了優(yōu)化synchonized,引入了輕量級(jí)鎖,偏向鎖。
十三、輕級(jí)鎖
應(yīng)用 鎖優(yōu)化技術(shù) 思想 輕量級(jí)鎖是在無(wú)競(jìng)爭(zhēng)的情況下使用CAS操作去消除同步使用的互斥量。 輕量級(jí)是相對(duì)于使用操作系統(tǒng)互斥量來(lái)實(shí)現(xiàn)的重量級(jí)鎖而言的。 輕量級(jí)鎖在沒(méi)有多線程競(jìng)爭(zhēng)的前提下,減少傳統(tǒng)的重量級(jí)鎖使用操作系統(tǒng)互斥量產(chǎn)生的性能消耗。 如果出現(xiàn)兩條以上的線程爭(zhēng)用同一個(gè)鎖的情況,那輕量級(jí)鎖將不會(huì)有效,必須膨脹為重量級(jí)鎖。 優(yōu)點(diǎn) 如果沒(méi)有競(jìng)爭(zhēng),通過(guò)CAS操作成功避免了使用互斥量的開(kāi)銷(xiāo) 缺點(diǎn) 如果存在競(jìng)爭(zhēng),除了互斥量本身的開(kāi)銷(xiāo)外,還額外產(chǎn)生了CAS操作的開(kāi)銷(xiāo),因此在有競(jìng)爭(zhēng)的情況下,輕量級(jí)鎖比傳統(tǒng)的重量級(jí)鎖更慢
到此這篇關(guān)于詳細(xì)介紹Java中的各種鎖的文章就介紹到這了,更多相關(guān)Java鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot快速實(shí)現(xiàn)接口消息加密的過(guò)程詳解
在項(xiàng)目中,為了保證數(shù)據(jù)的安全,我們常常會(huì)對(duì)傳遞的數(shù)據(jù)進(jìn)行加密,常用的加密算法包括對(duì)稱(chēng)加密(AES)和非對(duì)稱(chēng)加密(RSA),博主選取碼云上最簡(jiǎn)單的API加密項(xiàng)目進(jìn)行下面的講解,需要的朋友可以參考下2023-11-11Spring Boot項(xiàng)目集成UidGenerato的方法步驟
這篇文章主要介紹了Spring Boot項(xiàng)目集成UidGenerato的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Linux環(huán)境卸載Centos7自帶的OpenJDK和安裝JDK1.8圖文教程
CentOS系統(tǒng)是開(kāi)發(fā)者常用的Linux操作系統(tǒng),安裝它時(shí)會(huì)默認(rèn)安裝自帶的舊版本的OpenJDK,但在開(kāi)發(fā)者平時(shí)開(kāi)發(fā)Java項(xiàng)目時(shí)還是需要完整的JDK,這篇文章主要給大家介紹了關(guān)于Linux環(huán)境卸載Centos7自帶的OpenJDK和安裝JDK1.8的相關(guān)資料,需要的朋友可以參考下2024-07-07解決mybatis中order by排序無(wú)效問(wèn)題
這篇文章主要介紹了解決mybatis中order by排序無(wú)效問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12Java函數(shù)式編程(十二):監(jiān)控文件修改
這篇文章主要介紹了Java函數(shù)式編程(十二):監(jiān)控文件修改,本文是系列文章的第12篇,其它文章請(qǐng)參閱本文底部的相關(guān)文章,需要的朋友可以參考下2014-09-09java計(jì)算代碼段執(zhí)行時(shí)間的詳細(xì)代碼
java里計(jì)算代碼段執(zhí)行時(shí)間可以有兩種方法,一種是毫秒級(jí)別的計(jì)算,另一種是更精確的納秒級(jí)別的計(jì)算,這篇文章主要介紹了java計(jì)算代碼段執(zhí)行時(shí)間,需要的朋友可以參考下2022-08-08springboot+gradle 構(gòu)建多模塊項(xiàng)目的步驟
這篇文章主要介紹了springboot+gradle 構(gòu)建多模塊項(xiàng)目的步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05