大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節(jié)點(diǎn)LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 并發(fā)編程之cas原理分析

并發(fā)編程之cas原理分析

更新時間:2022-10-28 10:34:49 來源:動力節(jié)點(diǎn) 瀏覽1751次

首先認(rèn)識一下Java CAS多線程:CAS是支持并發(fā)的第一個處理器提供原子的測試并設(shè)置操作,通常在單位上運(yùn)行這項操作。操作數(shù)為V,A,B。

CAS 操作包含三個操作數(shù) —— 內(nèi)存位置(V)、預(yù)期原值(A)和新值(B)。如果內(nèi)存位置的值與預(yù)期原值相匹配,那么處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。無論哪種情況,它都會在 CAS 指令之前返回該位置的值。(在 CAS 的一些特殊情況下將僅返回 CAS 是否成功,而不提取當(dāng)前值。)CAS 有效地說明了“我認(rèn)為位置 V 應(yīng)該包含值 A;如果包含該值,則將 B 放到這個位置;否則,不要更改該位置,只告訴我這個位置的值即可。”

CAS 是處理器級別的原語,也就是說單核情況下處理器可以保證 CAS 操作的原子性。

但事實(shí)是多核環(huán)境下,CAS 的原子性也是可以得到保證的。在單核環(huán)境下保證原子性的基礎(chǔ)上,多核情況下 CAS 通過以下方式保證操作的原子性:

1. 通過總線鎖,保證其修改動作的線程排他性。

2. 通過緩存一致性協(xié)議,保證處理器緩存中的值對其它核心的可見性。

3. 多核環(huán)境下通過 lock 內(nèi)存屏障,保證多線程下的有序性,并保證其值立即從寫緩沖區(qū)刷新到緩存,結(jié)合2,保證了操作結(jié)果對其它核心的可見性。

我們看一下 Intel X86 架構(gòu)下 CAS 的一段實(shí)現(xiàn):

// Adding a lock prefix to an instruction on MP machine
// VC++ doesn't like the lock prefix to be on a single line
// so we can't insert a label after the lock prefix.
// By emitting a lock prefix, we can define a label after it.
#define LOCK_IF_MP(mp) __asm cmp mp, 0  \
                       __asm je L0      \
                       __asm _emit 0xF0 \
                       __asm L0:
inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  // alternative for InterlockedCompareExchange
  int mp = os::is_MP();
  __asm {
    mov edx, dest
    mov ecx, exchange_value
    mov eax, compare_value
    LOCK_IF_MP(mp)
    cmpxchg dword ptr [edx], ecx
  }
}

程序會根據(jù)當(dāng)前處理器的類型來決定是否為cmpxchg指令添加lock前綴。如果程序是在多處理器上運(yùn)行,就為cmpxchg指令加上lock前綴(lock cmpxchg)。反之,如果程序是在單處理器上運(yùn)行,就省略lock前綴。

因?yàn)榈幚砥髑闆r下,有序性有天然的保證。同時不需要強(qiáng)制將結(jié)果從緩沖區(qū)刷新入緩存,因?yàn)樘幚砥髟谧x取值時會先從寫緩沖區(qū)中尋找,找不到才回去緩存中尋找,所以單核情況下無論是否將結(jié)果刷入緩存,操作結(jié)果都是對所有線程可見的。

可以看到 CAS 保證可見性與有序性的原理與 volatile 一樣,都是通過處理器提供的內(nèi)存屏障,盡管它們不在一個抽象層級的,這樣比較并不合適。

CAS 效率的一個重要影響因素是cache miss,如果 CAS 操作的內(nèi)存地址不在當(dāng)前處理器的緩存中的話,需要通過緩存一致性協(xié)議在其它處理器的緩存中尋找,如果都找不到則去內(nèi)存加載。最好情況下,也就是沒有發(fā)生 cache miss 的話,CAS 大概需要 60 個時鐘周期,而鎖操作在最好情況下需要大約 100 個時鐘周期(一個“round trip 對”包括獲取鎖和隨后的釋放鎖),通常情況下 CAS 的效率是高于鎖操作的。

CAS 是一種樂觀鎖,再補(bǔ)充一下樂觀鎖與悲觀鎖:

悲觀鎖,正如其名,具有強(qiáng)烈的獨(dú)占和排他特性。它指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度。因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機(jī)制(也只有數(shù)據(jù)庫層提供的鎖機(jī)制才能真正保證數(shù)據(jù)訪問的排他性,否則,即使在本系統(tǒng)中實(shí)現(xiàn)了加鎖機(jī)制,也無法保證外部系統(tǒng)不會修改數(shù)據(jù))。

之所以叫做悲觀鎖,是因?yàn)檫@是一種對數(shù)據(jù)的修改抱有悲觀態(tài)度的并發(fā)控制方式。我們一般認(rèn)為數(shù)據(jù)被并發(fā)修改的概率比較大,所以需要在修改之前先加鎖。悲觀并發(fā)控制實(shí)際上是“先取鎖再訪問”的保守策略,為數(shù)據(jù)處理的安全提供了保證。

樂觀鎖機(jī)制采取了更加寬松的加鎖機(jī)制。樂觀鎖是相對悲觀鎖而言,也是為了避免數(shù)據(jù)庫幻讀、業(yè)務(wù)處理時間過長等原因引起數(shù)據(jù)處理錯誤的一種機(jī)制,但樂觀鎖不會刻意使用數(shù)據(jù)庫本身的鎖機(jī)制,而是依據(jù)數(shù)據(jù)本身來保證數(shù)據(jù)的正確性。

相對于悲觀鎖,在對數(shù)據(jù)庫進(jìn)行處理的時候,樂觀鎖并不會使用數(shù)據(jù)庫提供的鎖機(jī)制。一般的實(shí)現(xiàn)樂觀鎖的方式就是記錄數(shù)據(jù)版本。樂觀并發(fā)控制相信事務(wù)之間的數(shù)據(jù)競爭(data race)的概率是比較小的,因此盡可能直接做下去,直到提交的時候才去鎖定,所以不會產(chǎn)生任何鎖和死鎖。

每種機(jī)制都不是十全十美的,有優(yōu)點(diǎn)必然也有缺點(diǎn),我們來看一下 CAS 的缺點(diǎn):

1.cpu開銷大,在高并發(fā)下,許多線程,更新一變量,多次更新不成功,循環(huán)反復(fù),給cpu帶來大量壓力。

2.只是一個變量的原子性操作,不能保證代碼塊的原子性。

3.ABA問題

ABA問題:內(nèi)存值V=100;

threadA 將50,改為0;

threadB 將50,改為0;

threadC 將0,改為50

正常情況下 A 執(zhí)行完 B 應(yīng)該失敗,但是如果 B 阻塞住了,期間 C 執(zhí)行成功,那么 A 與 B 都可以執(zhí)行成功,一次本應(yīng)該失敗的操作成功了。因?yàn)椴皇窍壬湘i再操作,所以我們不能保證線程對共享變量訪問的有序性(這可不是三大特性里的有序性),這樣在實(shí)際生產(chǎn)過程中,因?yàn)槊總€操作都有自己的意義,亂序的訪問共享變量會導(dǎo)致操作錯誤。

比如一杯水,A喝完了,B倒?jié)M了,C又喝完了。C無法分辨杯子里的水有沒有被人喝過,項目中的邏輯很可能是如果杯子被人用過,C就不喝了,但是B將其倒?jié)M導(dǎo)致C無法對該條件進(jìn)行正確的判斷。在特定情況下,我們不能只看數(shù)據(jù)的當(dāng)前值,也應(yīng)該看數(shù)據(jù)的狀態(tài),我們可以為數(shù)據(jù)增加一個狀態(tài)--版本號來解決這個問題。

其實(shí)悲觀鎖也存在ABA問題,碰到這種情況也需要為數(shù)據(jù)增加一個狀態(tài)來監(jiān)控數(shù)據(jù)。但是悲觀鎖并不是根據(jù)數(shù)據(jù)的當(dāng)前狀態(tài)來判斷操作是否執(zhí)行的,而是有鎖的邏輯,所以我們在編寫程序時本身就不會出現(xiàn)原值被改過又被改回來所以我能執(zhí)行這種邏輯漏洞,我們會有其它控制位來調(diào)度線程的執(zhí)行。

在JDK1.5之后,Java程序中才可以使用CAS操作,該操作由sun.misc.Unsafe類里面的compareAndSwapInt()和compareAndSwapLong()等幾個方法包裝提供,虛擬機(jī)在內(nèi)部對這些方法做了特殊處理,即時編譯出來的結(jié)果就是一條平臺相關(guān)的處理器CAS指令,沒有方法調(diào)用的過程,或者可以認(rèn)為是無條件內(nèi)聯(lián)進(jìn)去了。

由于Unsafe類不是提供給用戶提供調(diào)用的類(Unsafe.getUnsafe()的代碼中限制了只有啟動類加載器(Bootstrap ClassLoader)加載的Class才能訪問它),因此,如果不采用反射手段,我們只能通過其他的Java API來間接使用它,如J.U.C包里面的整數(shù)原子類,其中的 compareAndSet()和 getAndIncrement()等方法都使用了 Unsafe 類的 CAS 操作。如果大家想了解更多相關(guān)知識,不妨來關(guān)注一下本站的Java多線程編程,里面還有更豐富的知識等著大家去學(xué)習(xí),希望對大家能夠有所幫助。

提交申請后,顧問老師會電話與您溝通安排學(xué)習(xí)

免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 尤物视频在线 | 久久久久久a亚洲欧洲aⅴ | 久久久国产99久久国产久 | 色综合欧美色综合七久久 | 国产成人一区二区三区视频免费蜜 | 国产视频精品视频 | 色视屏 | 96精彩视频在线观看 | 99久久综合久中文字幕 | 国产在线播放一区二区 | 中文字幕在线免费播放 | 999精品视频这里只有精品 | 伊人久久五月天 | 毛片8| 亚洲五月婷婷 | 国产女人成人精品视频 | 亚洲欧美另类视频 | 四虎影视在线影院在线观看观看 | 麻豆精品国产免费观看 | 国产精品合集一区二区 | 欧美精品久久 | 99久久免费精品国产免费高清 | 国产成+人+综合+亚洲 欧美 | 大学生一级黄色片 | 免费的一级片网站 | 激情五月婷婷色 | jizz人妖 | 337p欧美超大胆日本人术艺术 | 成人毛片高清视频观看 | xxxxx日本59| 欧美美女一区 | 国产一区a | 在线成人tv天堂中文字幕 | 99久久精品久久久久久清纯 | 欧美成人极品怡红院tv | 爱爱小视频免费体验区在线观看 | 欧洲欧美成人免费大片 | 精品日本亚洲一区二区三区 | 日韩经典中文字幕 | 国产精品久久久久一区二区 | 精品久久久久久免费影院 |