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