日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面试必问!有没有比读写锁更快的锁?

發(fā)布時(shí)間:2025/3/21 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试必问!有没有比读写锁更快的锁? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

面試三連

面試官:了解鎖嗎?

小明:了解,還經(jīng)常用過。

面試官:說說synchronized和lock的區(qū)別吧

小明:synchronized是可重入鎖,由于lock是一個(gè)接口,重入性取決于實(shí)現(xiàn),synchronized不支持中斷,而lock可以。。。。。。。。。。。。。。。。

面試官:好了,那有沒有比這兩種鎖更快的鎖呢?

小明:在讀多寫少的情況下,讀寫鎖比他們的效率更高。

面試官:那有沒有比讀寫鎖更快的鎖呢?

小明:。。。。。。。。。。

我靠,問的這么深的嗎?小明當(dāng)時(shí)就蒙蔽了,因?yàn)樗?xiàng)目中使用比較多的就是synchronized,讀寫鎖都很少用到,因?yàn)楹苌贍砍兜蕉嗑€程問題,這個(gè)面試讓他知道了多線程的重要性。

?

什么是讀寫鎖

讀寫鎖:允許多個(gè)線程同時(shí)讀,但是只允許一個(gè)線程寫,在線程獲取到寫鎖的時(shí)候,其他寫操作和讀操作都會(huì)處于阻塞狀態(tài),讀鎖和寫鎖也是互斥的,所以在讀的時(shí)候是不允許寫的,那如何實(shí)現(xiàn)一個(gè)讀寫鎖呢?

讀寫鎖比傳統(tǒng)的synchronized速度要快很多,原因就是在于讀寫鎖支持讀并發(fā),而synchronized要求所有操作都是串行化,舉個(gè)例子,我需要查詢某個(gè)用戶的基本信息,這些信息很少發(fā)生變化,所以我們會(huì)將這部分信息存放到緩存中,我們的查詢操作為:

按照上面流程圖,如果使用synchronized的時(shí)候,查詢緩存都會(huì)阻塞,但是使用讀寫鎖,查詢緩存時(shí)并發(fā)的,查詢數(shù)據(jù)庫是阻塞的,所以,讀寫鎖在讀多寫少的情況下,性能明顯要優(yōu)于synchronized。

人類的文明在進(jìn)步,java也在進(jìn)步,對知識的渴望也在不斷的增加,所以我們就不斷的在想這么一個(gè)問題,讀寫鎖的讀和寫是互斥,那我們能不能做到讀和寫支持并發(fā)呢?

StampedLock橫空出世

StampedLock其實(shí)是對讀寫鎖的一種改進(jìn),它支持在讀同時(shí)進(jìn)行一個(gè)寫操作,也就是說,它的性能將會(huì)比讀寫鎖更快。

更通俗的講就是在讀鎖沒有釋放的時(shí)候是可以獲取到一個(gè)寫鎖,獲取到寫鎖之后,讀鎖阻塞,這一點(diǎn)和讀寫鎖一致,唯一的區(qū)別在于讀寫鎖不支持在沒有釋放讀鎖的時(shí)候獲取寫鎖。

StampedLock三種模式

悲觀讀:與讀寫鎖的讀寫類似,允許多個(gè)線程獲取悲觀讀鎖

寫鎖:與讀寫鎖的寫鎖類似,寫鎖和悲觀讀是互斥的。

樂觀讀:無鎖機(jī)制,類似于數(shù)據(jù)庫中的樂觀鎖,它支持在不是放寫鎖的時(shí)候是可以獲取到一個(gè)寫鎖的,這點(diǎn)和讀寫鎖不同。

基本語法

我們先來看看悲觀讀于與寫鎖的基本語法

我們看到,StampedLock語法和讀寫鎖ReentrantReadWriteLock有了一點(diǎn)點(diǎn)區(qū)別,

獲取鎖的返回值:

StampedLock:long

ReentrantReadWriteLock:Lock

釋放鎖的方式:

StampedLock:unlock(stamp),需要傳入獲取鎖返回的那個(gè)long值。

ReentrantReadWriteLock:unlock(),直接調(diào)用unlock方法即可。

這是悲觀讀+寫鎖的使用方式,達(dá)到的效果與讀寫鎖(ReentrantReadWriteLock) 是一樣的,我們一起來驗(yàn)證一下,我將代碼稍微做了一點(diǎn)改動(dòng),打印了兩個(gè)線程的執(zhí)行日志,同時(shí)當(dāng)調(diào)用線程是zhangsan的時(shí)候休眠三秒,目的是為了看lisi的線程能否成功的獲取到寫鎖,代碼如下

如果在zhansan的線程休眠階段李四的線程獲取到了寫鎖,那么代表悲觀讀和寫鎖不是互斥的,反之互斥,請看代碼運(yùn)行結(jié)果:

我們仔細(xì)看打印日志的輸出時(shí)間, 11:30:58 lisi和zhangsan都獲取到了悲觀讀鎖,并且zhangsan開始休眠,然后11:31:01的時(shí)候休眠結(jié)束,zhangsan獲取到了寫鎖,所以悲觀讀與寫鎖肯定是互斥的,那這樣的效率不是和讀寫鎖一樣嗎?為什么說它比讀寫鎖更快呢?這不是矛盾嗎?

客官,別急啊,要記住精彩的永遠(yuǎn)在最后,StampedLock特鎖模式我們只用了其中的兩個(gè),還有一個(gè)沒有出場呢,下面我們來看看樂觀讀。

?

讓StampedLock性能更上一樓的樂觀讀

樂觀讀并不是一種鎖,所以請不要和悲觀讀聯(lián)系在一起,它是一種無鎖機(jī)制,相當(dāng)于java的原子類操作,所以理論上性能會(huì)比讀寫鎖(ReentrantReadWriteLock)更快一點(diǎn),但不絕對。

當(dāng)樂觀讀讀取了成員變量的時(shí)候,需要將變量賦值給局部變量,然后再判斷程序運(yùn)行期間是否存在寫鎖,如果存在,升級為悲觀讀。

我們一起來看一下樂觀讀的實(shí)現(xiàn)

解釋代碼,定義了兩個(gè)成員變量,讓后利用t1線程去計(jì)算兩個(gè)成員變量的和,為了能體現(xiàn)出樂觀讀的效果,我在sum()中休眠了3秒,目的是讓main主線程去修改掉成員變量的值,main函數(shù)中的休眠是為了讓t1線程能準(zhǔn)確地執(zhí)行到讀取成員變量階段。

我們來看看執(zhí)行的結(jié)果:

我們發(fā)現(xiàn),t1首先讀取了兩個(gè)成員變量的值,然后發(fā)現(xiàn)了存在寫操作,那是因?yàn)閙ain函數(shù)利用寫鎖修改了兩個(gè)成員變量的值,這個(gè)時(shí)候升級為了悲觀讀,再次獲取成員變量的值,然后再計(jì)算兩個(gè)值的和,為什么要升級悲觀讀鎖呢?因?yàn)樵傥恼麻_頭的時(shí)候說過悲觀讀鎖與寫鎖互斥,悲觀讀鎖之前并行,所以樂觀讀升級到悲觀讀鎖之后再獲取一次成員變量,可以保證再當(dāng)前悲觀讀鎖中數(shù)據(jù)是線程安全的。

使用StampedLock的注意事項(xiàng)

1.StampedLock屬于ReadWriteLock的子類,ReentrantReadWriteLock也是屬于ReadWriteLock的子類,你們發(fā)現(xiàn)他們的區(qū)別了嗎?看名字就能看出來StampedLock不支持重入鎖。

2.它適用于讀多寫少的情況,如果不是這中情況,請慎用,性能可能還不如synchronized。

3.StampedLock的悲觀讀鎖、寫鎖不支持條件變量。

4.千萬不能中斷阻塞的悲觀讀鎖或?qū)戞i,如果調(diào)用阻塞線程的interrupt(),會(huì)導(dǎo)致cpu飆升,如果希望StampedLock支持中斷操作,請使用readLockInterruptibly(悲觀讀鎖)與writeLockInterruptibly(寫鎖)。

?

總結(jié)

在讀多寫少的情況下推薦使用StampedLock,因?yàn)樗臉酚^讀,性能比讀寫鎖提升了很多,但是再其他應(yīng)用場景中,使用它還需要慎重。

?

樂觀讀支持并發(fā)一個(gè)寫鎖,而悲觀讀和寫鎖互斥,所以在使用過程中,我們可以先使用樂觀讀。然后判斷是否存在寫鎖,如果存在,可以升級悲觀讀鎖,由于悲觀讀鎖和寫鎖的互斥性,他能保證線程的安全性問題,如果小明再平時(shí)的時(shí)候多看看我的博客的話,可能就不會(huì)被這個(gè)問題難住了。

總結(jié)

以上是生活随笔為你收集整理的面试必问!有没有比读写锁更快的锁?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。