當前位置:首頁 » 文件管理 » cas緩存鎖

cas緩存鎖

發布時間: 2023-03-21 02:58:07

『壹』 原子操作的實現原理

我們一起來聊一聊在Inter處理器和java里是如何實現原子操作的。

32位IA-32處理器使用基於緩存加鎖或匯流排加鎖 的方式來實現多處理器之間的原子操作

首先處理器會自動保證基本的內存操作的原子性。 處理器保證從系統內存當中讀取或者寫入一個位元組是原子的,意思是當一個處理器讀取一個位元組時,其他處理器不能訪問這個位元組的內存地址。奔騰6和最新的處理器能自動保證單處理器對同一個緩存行里進行16/32/64位的操作是原子的,但是復雜的內存操作處理器不能自動保證其原子性,比如跨匯流排寬度,跨多個緩存行,跨頁表的訪問。但是處理器提供匯流排鎖定和緩存鎖定兩個機制來保證復雜內存操作的原子性。

第一個機制是通過匯流排鎖保證原子性。 如果多個處理器同時對共享變數進行讀改寫(i++就是經典的讀改寫操作)操作,那麼共享變數就會被多個處理器同時進行操作,這樣讀改寫操作就不是原子的,操作完之後共享變數的值會和期望的不一致,舉個例子:如果i=1,我們進行兩次i++操作,我們期望的結果是3,但是有可能結果是2。如下圖

處理器使用匯流排鎖就是來解決這個問題的。 所謂匯流排鎖就是使用處理器提供的一個LOCK#信號,當一個處理器在匯流排上輸出此信號時,其他處理器的請求將被阻塞住,那麼該處理器可以獨占使用共享內存。

「緩存鎖定」指內存區域如果被緩存在處理器的緩存行中,並且在Lock操作期間被鎖定,那麼當它執行鎖操作回寫到內存時,處理器不需要在匯流排上聲言LOCK#信號,而是修改內部的內存地址,通過緩存一致性機制保證操作的原子性。
例外:當操作的數據不能被緩存在處理器內部,或操作的數據跨多個緩存行,處理器會調用匯流排鎖定。

在java中可以通過鎖和循環CAS的方式來實現原子操作。
CAS

ABA問題
循環時間長開銷大
只能保證一個共享變數的原子操作

原子操作的實現原理
聊聊並發(五)原子操作的實現原理

『貳』 幾句話總結CAS鎖與synchronized差異

其實網上有很多做過實驗對比的,這里就不一一敘述了,
總的來說就是,競爭少的情況喊伍汪下CAS優於synchronized,反之synchronized優於CAS。
剛開始接觸CAS的時候,一聽說是鎖,還是非阻塞的,就覺得肯定比加鎖快,其實不然,還是得透過現象看本質,不要管中窺豹。
我嘗試用幾句話總結:

根據上述,我們可以知道,CAS失敗的情況下,自旋鎖會一直旋轉,synchronized雖然不會旋轉,但是在獲得鎖的情況下,除了異常,其他情況下是肯定成功的。
所以兩者的時間差別就是,自旋的時間和線程上下文切換的時間,雖然在其他資源在充足情況下,自旋成功下的時間肯定比線鄭仔程加鎖要來的快,但是你考慮橘粗下,如果競爭很激烈的情況下,是不是只有一個CAS能成功,那麼其他的都是失敗自旋,那麼在這種情況下,CPU的資源的消耗可以說十分大的,那我還不如給這個共享資源加鎖,剩下的線程等待不佔用CPU資源,這種情況下,你可以考慮負載均衡,你可以考慮在別的情況下並行或者並發處理別的事務,都可以,否則如果遇到stop world 的情況就得不償失了。
希望大家指點和交流,謝謝!

『叄』 CAS在項目中的應用

模擬一般搶購活動中需要加鎖的程序,採用synchronized鎖與CAS鎖,比較二者的性能。說明二者的區別,並指出合適應該使用CAS鎖。

首先創建一個spring boot 的項目,不修改任何默認tomcat的配置,模擬搶購程序耗時100ms

這些程序的失敗只是說明在壓測是時間內程序沒有響應(5s以上),後台繼續在運行,用監控工具可以看到

實際上處理完1000個線程耗時的時間是兩分含族首鍾(visualVM反應有點小遲鈍),並且可以大致看出spring boot 默認的線程數大概在200(還有一些程序存談數活的守護線程,我們並不能利用起來),在內存時序圖中,可以大致看到,新建一個線程,大概消耗10m的內存。

這些意味著如果你採用synchronized,兩分鍾內,你的服務處於假死狀態(tomcat的線程被占完),不做測試的話其實也能估算出大概的耗時,畢竟主要就是搶購程序內部耗時,每個100ms,1000個就是兩分鍾左右,加鎖的性能很低,不到萬不得已不要加重鎖。

換成CAS的操作

根據測試的結果,可以大致判斷CAS鎖的使用場景:快速響應失敗。比如會穗茄場活動,或者需要連續點擊的搶購,不需要按時間點擊順序(這個需要mq的幫助)確定搶購結果的活動。

『肆』 每日一問:談談 synchronized 和 CAS 機制

昨天的文章 我們針對 Java 語言的 "happends-before" 原則做了一個非常簡單的表述,以致於有同學提到我這個話語的嚴謹性問題。而這個原則在 Java 語言裡面非常重要,以致於我必須重新引用一下相關書籍的話來進行論述。

"happends-before" 先行發生原則是 Java 內存模型中定義的兩項操作之間的偏序關系,如果說操作 A 先行發生於操作 B,那麼操作 A 產生的影響一定應該被操作 B 所觀察到。

而對於我們 volatile 保證的可見性, synchronized 和 final 關鍵字也同樣可以做到。那我們今天就來簡單講一下我們非常常用的 synchronized 和似乎在 Android 中少有聽到的 CAS 機制。

synchronized 採用的是 CPU 悲觀鎖機制,即線程獲得的是獨占鎖。獨占鎖就意味著 其他線程只能依靠阻塞來等待線程釋放鎖 。而在 CPU 轉換線程阻塞時會引起線程上下文切換,當有很多線程競爭鎖的時候,會引起 CPU 頻繁的攔碧上下文切換導致效率很低。盡管 Java1.6 為 synchronized 做了優化,增加了從偏向鎖到輕量級鎖再到重量級鎖的正早過度,但是在最終轉變為重量級鎖之後,性能仍然簡清舉較低。

CAS 是英文單詞 Compare And Swap 的縮寫,翻譯過來就是比較並替換。它當中使用了3個基本操作數:內存地址 V,舊的預期值 A,要修改的新值 B。採用的是一種樂觀鎖的機制,它不會阻塞任何線程,所以在效率上,它會比 synchronized 要高。所謂樂觀鎖就是: 每次不加鎖而是假設沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。

所以,在並發量非常高的情況下,我們盡量的用同步鎖,而在其他情況下,我們可以靈活的採用 CAS 機制。

在 java.util.concurrent.atomic 包下,一系列以 Atomic 開頭的包裝類。例如 AtomicBoolean , AtomicInteger , AtomicLong 等,它們就是典型的利用 CAS 機制實現的原子操作類。

此外, Lock 系列類的底層實現以及 Java 1.6 在 synchronized 轉換為重量級鎖之前,也會採用到 CAS 機制。

關於 CAS 機制的更多相關信息請移步:
漫畫:什麼是CAS機制?(進階篇)

『伍』 CAS原理以及CAS帶來的三大問題

參考: https://www.jianshu.com/p/ab2c8fce878b
https://www.jianshu.com/p/68f9cd012de8

CAS :Compare and Swap,即比較再交換。

CAS演算法理解 :CAS是一種無鎖演算法,CAS有3個操作數,內存值E,舊的預期值V,要修改的新值N。當且僅當預期值V和內存值E相同時,將內存值E修改為N,否則什麼都不做。

CAS演算法圖解

上圖描述了CAS的原理,以及帶來的三大問題以及問題出運粗現的位置。

1.ABA問題
因為CAS需要在操作值的時候,檢查值有沒有發生變化,如果沒有發生變化則更新,但是如果一個值原來是A,變成了B,又變成了A,那麼CAS進行檢查的時候發現它的值沒有發生變化,但是實際上卻變化了。ABA問題的解決思路就是使用版本號。在變數前面加上版本號,每次變數更新的時候把版本號加1,那麼A->B->A就會變成1A->2B->3A。從Java 1.5開始,JDK的Atomic包里提供了一個類AtomicStampedReference來解決ABA問題。這個類的compareAndSet方法的作用是首先檢查當前引用是否等於預期引用,並且檢查當前的標志是否等於預期標志,如果全部相等,則以原子方式將該應用和該標志的值設置為給定的更新值。

2.循環時間長開銷大
自旋CAS如果長時間不成功,會給CPU帶來非常大的執行開銷,如果JVM能旁雀鎮支持處理器提供的pause指令,那麼效率會有一定的提升。pause指令有兩個作用:第一,它可以延遲流水線執行指令(de-pipeline),使CPU不會消耗過多的執行資源,延遲的時間取決於具體實現的版本,在一些處理器上延遲時間是零;第二,它可以避免在循環的歲亮時候因內存順序沖突(Memory Order Violation)而引起CPU流水線被清空,從而提高CPU的實行效率。

3.只能保證一個共享變數的原子操作
當對一個共享變數執行操作時,我們可以使用循環CAS的方式來保證原子操作,但是對多個共享變數操作時,循環CAS就無法保證操作的原子性,這個時候可以用鎖。還有一個取巧的辦法,就是把多個共享變數合並成一個共享變數來操作。比如,有兩個共享變數i=2,j=a,合並一下ji=2a,然後用CAS來操作ij。從Java 1.5開始,JDK提供了AtomicReference類來保證引用對象之前的原子性,就可以把多個變數放在一個對象里來進行CAS操作。

熱點內容
java返回this 發布:2025-10-20 08:28:16 瀏覽:710
製作腳本網站 發布:2025-10-20 08:17:34 瀏覽:972
python中的init方法 發布:2025-10-20 08:17:33 瀏覽:681
圖案密碼什麼意思 發布:2025-10-20 08:16:56 瀏覽:833
怎麼清理微信視頻緩存 發布:2025-10-20 08:12:37 瀏覽:740
c語言編譯器怎麼看執行過程 發布:2025-10-20 08:00:32 瀏覽:1080
郵箱如何填寫發信伺服器 發布:2025-10-20 07:45:27 瀏覽:311
shell腳本入門案例 發布:2025-10-20 07:44:45 瀏覽:191
怎麼上傳照片瀏覽上傳 發布:2025-10-20 07:44:03 瀏覽:878
python股票數據獲取 發布:2025-10-20 07:39:44 瀏覽:835