非互斥同步锁
樂(lè)觀鎖
- 認(rèn)為自己在處理操作的時(shí)候不會(huì)有其他線程阿里干擾,所以并不會(huì)鎖住被操作對(duì)象
- 在更新的時(shí)候,去對(duì)比在我修改的期間數(shù)據(jù)有沒(méi)有被其他人改變過(guò),如果沒(méi)有被改變過(guò),就說(shuō)明真的是只有我自己在操作,那我就正常去修改數(shù)據(jù);如果數(shù)據(jù)和我一開(kāi)始拿到的不一樣了,說(shuō)明其他人在這段時(shí)間內(nèi)修改過(guò)數(shù)據(jù),那么我就不能繼續(xù)剛才的更新數(shù)據(jù)過(guò)程了,我會(huì)選擇放棄、報(bào)錯(cuò)、重試等
- 樂(lè)觀鎖的實(shí)現(xiàn)一般都是利用CAS算法來(lái)實(shí)現(xiàn)的
典型例子
- 悲觀鎖:synchronized和Lock相關(guān)的類
- 樂(lè)觀鎖的典型例子就是原子類、并發(fā)容器等
- Git:Git就是樂(lè)觀鎖的典型例子,當(dāng)我們往遠(yuǎn)程倉(cāng)庫(kù)push的時(shí)候,git會(huì)檢查遠(yuǎn)程倉(cāng)庫(kù)的版本是不是領(lǐng)先于我們現(xiàn)在的版本,如果遠(yuǎn)程倉(cāng)庫(kù)的版本號(hào)和本地的不一樣,就表示有其他人修改了遠(yuǎn)端代碼,那么我們這次提交就失敗,如果遠(yuǎn)端和本地的版本號(hào)一致,我們就可以順利提交版本到遠(yuǎn)端倉(cāng)庫(kù)
- 數(shù)據(jù)庫(kù):select for update就是悲觀鎖;使用version控制數(shù)據(jù)庫(kù)的數(shù)據(jù),那么就是樂(lè)觀鎖
悲觀鎖和樂(lè)觀鎖開(kāi)銷對(duì)比
- 悲觀鎖的開(kāi)始開(kāi)銷要高于樂(lè)觀鎖,但是特點(diǎn)是一勞永逸,臨界區(qū)持鎖時(shí)間就算越來(lái)越差,也不會(huì)對(duì)互斥鎖的開(kāi)銷造成影響
- 相反,雖然樂(lè)觀鎖一開(kāi)始的開(kāi)銷比悲觀鎖小,但是如果自旋時(shí)間很長(zhǎng)或者不停重試,那么消耗的資源也會(huì)越來(lái)越多
悲觀鎖和樂(lè)觀鎖的使用場(chǎng)景
- 悲觀鎖:適合并發(fā)寫(xiě)入多的情況,適用于臨界區(qū)持鎖時(shí)間比較長(zhǎng)的情況,悲觀鎖可以避免大量的無(wú)用自旋等消耗,典型情況:
- 臨界區(qū)有I/O操作
- 臨界區(qū)代碼復(fù)雜或循環(huán)量大
- 臨界區(qū)競(jìng)爭(zhēng)非常激烈
- 樂(lè)觀鎖:適合并發(fā)寫(xiě)入少,大部分是讀取的場(chǎng)景,不加鎖能讓讀取性能大幅提高
?
總結(jié)