前言
synchronized和Lock通過互斥保障原子性堂污,能夠保護(hù)共享數(shù)據(jù)以實(shí)現(xiàn)線程安全,其作用包括保障原子性官紫、可見性引瀑、有序性
常見問題
在平時(shí)聊天或者面試過程中狂芋,可能會(huì)被問到,既然已經(jīng)有了synchronized了憨栽,為什么JSR166小組花這么多時(shí)間來開發(fā)j.u.c的Lock框架呢帜矾,換句話說就是內(nèi)部鎖和顯示鎖之前有什么區(qū)別?
分析
synchronized(內(nèi)部鎖)
java平臺(tái)中的任何一個(gè)對(duì)象都有唯一一個(gè)與之關(guān)聯(lián)的鎖屑柔,這種鎖稱為監(jiān)視器(Monitor)或者內(nèi)部鎖(Intrinsic Lock),內(nèi)部鎖是通過synchronized關(guān)鍵字實(shí)現(xiàn)的屡萤,可以用來修飾方法(同步方法、靜態(tài)方法)锯蛀、代碼塊(臨界區(qū))
Lock(顯示鎖)
JDK1.5開始引入的排他鎖灭衷,默認(rèn)實(shí)現(xiàn)是ReetrantLock次慢,作為一種線程同步機(jī)制旁涤,其擁有和synchronized相同的語義翔曲,并且還提供了一些synchronized不具備的特性
差異
從本質(zhì)上來講
synchronized是在JVM層面實(shí)現(xiàn)的,
ReetrantLock是java API層面實(shí)現(xiàn)的排它鎖劈愚,系統(tǒng)無法自動(dòng)釋放鎖瞳遍,需要在代碼中的finally子句中顯示釋放,否則會(huì)出現(xiàn)鎖泄漏
從安全上來講
內(nèi)部鎖在退出臨界出時(shí)菌羽,會(huì)自動(dòng)釋放鎖掠械,不會(huì)導(dǎo)致鎖泄漏
外部鎖如果未主動(dòng)釋放鎖或者釋放代碼在finally子句中,容易導(dǎo)致鎖泄漏
從使用上來講
synchronized可以修飾方法注祖,修飾代碼塊猾蒂,但是內(nèi)部鎖的申請(qǐng)與釋放只能在一個(gè)方法內(nèi)進(jìn)行,因?yàn)榇a無法跨方法
Lock是晨,只能修飾代碼塊肚菠,但是它可以發(fā)揮面向?qū)ο缶幊痰撵`活性,顯示鎖的申請(qǐng)?jiān)谝粋€(gè)方法罩缴,在另一個(gè)方法里釋放鎖
在鎖的調(diào)度方面
內(nèi)部鎖公公平鎖蚊逢,顯示鎖即支持非公平也支持公平鎖
在問題定位方面
線程轉(zhuǎn)儲(chǔ)可能無法包含顯示鎖的相關(guān)信息,從而導(dǎo)致問題定位困難箫章。比如果在JDK1.5下線程轉(zhuǎn)儲(chǔ)中會(huì)包含內(nèi)部鎖的相關(guān)信息烙荷,不包含顯示鎖的信息
從性能方面方面
等待同一把內(nèi)部鎖的線程,都在同一個(gè)等待隊(duì)列中檬寂,等待系統(tǒng)調(diào)度终抽,而ReentrantLock鎖,可以通過Condition條件變量桶至,實(shí)現(xiàn)分組等待的效果拿诸,所以性能表現(xiàn)上更好一些
從其它特性方面
當(dāng)一個(gè)線程在等待獲取一個(gè)鎖時(shí),因?yàn)榫€程活性故障導(dǎo)致其永遠(yuǎn)無法獲取得鎖時(shí)塞茅,使用內(nèi)部鎖的線程會(huì)一直傻傻的等待一個(gè)無法獲得的鎖亩码,換句話說,內(nèi)部鎖缺少可中斷的特性野瘦,
顯示鎖它擁有與內(nèi)部鎖相同的并發(fā)性和內(nèi)存主義描沟,但是添加了輪詢鎖
、定時(shí)鎖等候
鞭光、可中斷鎖等候
一些新特性吏廉,使其在激烈爭(zhēng)用情況下表現(xiàn)出更好的性能,因?yàn)楫?dāng)多線程訪問共享資源時(shí)惰许,JVM可以將更多的時(shí)間用于執(zhí)行線程上席覆,而不是浪費(fèi)時(shí)間在線程調(diào)度上。
輪詢鎖意味著汹买,ReentrantLock支持公平鎖佩伤,可以通過輪詢的方式依次獲取鎖
定時(shí)鎖等候意味著聊倔,線程在N長(zhǎng)時(shí)間之內(nèi)無法獲取到鎖,就會(huì)返回false ,表示獲取鎖失敗生巡,tryLock方法耙蔑,不會(huì)像內(nèi)部鎖一樣癡癡的等待一個(gè)沒有結(jié)果的未來
可中斷鎖等待,意味著ReentrantLock提供了一種能夠中斷等待鎖的線程的機(jī)制孤荣,通過
lock.lockInterruptibly()
來實(shí)現(xiàn)這個(gè)機(jī)制甸陌。
如何選擇
如果你使用的是JDK1.5的話,在爭(zhēng)用不高的時(shí)候可以使用內(nèi)部鎖盐股,在爭(zhēng)用高的情況下钱豁,建議使用顯示鎖
如果你使用的是JDK1.5+的版本,隨著對(duì)內(nèi)部鎖的優(yōu)化(鎖消除疯汁、鎖粗化寥院、偏向鎖、自適應(yīng)鎖)涛目,兩都之間的性能差異已經(jīng)縮小了很多秸谢,如果后期內(nèi)部鎖的這些優(yōu)化可以應(yīng)用到顯示鎖的話,那性能可能就會(huì)有很大差距了霹肝。
總體上來說估蹄,在資源競(jìng)爭(zhēng)不激烈的情形下,性能稍微比synchronized差點(diǎn)點(diǎn)沫换。但是資源競(jìng)爭(zhēng)非常激烈的時(shí)候臭蚁,synchronized的性能會(huì)下降很多,而ReentrantLock的性能表現(xiàn)仍然比較穩(wěn)定讯赏。
結(jié)束語
在工作中垮兑,為了保證線程安全我們不一定要使用鎖,可以使用一些輕量級(jí)的同步工具或者無鎖的框架和工具漱挎,來提升應(yīng)用的性能系枪。
喜歡可以收藏我的個(gè)人博客