日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

Java性能 -- CAS樂觀鎖

 

synchronized / Lock / CAS

  1. synchronized和Lock實現(xiàn)的同步鎖機制,都屬于悲觀鎖,而CAS屬于樂觀鎖
  2. 悲觀鎖在高并發(fā)的場景下,激烈的鎖競爭會造成線程阻塞,而大量阻塞線程會導(dǎo)致系統(tǒng)的上下文切換,增加系統(tǒng)的性能開銷

樂觀鎖

  1. 樂觀鎖:在操作共享資源時,總是抱著樂觀的態(tài)度進(jìn)行,認(rèn)為自己能夠完成操作
  2. 但實際上,當(dāng)多個線程同時操作一個共享資源時,只有一個線程會成功,失敗的線程不會被掛起,僅僅只是返回
  3. 樂觀鎖相比于悲觀鎖來說,不會帶來死鎖、饑餓等活性故障問題,線程間的相互影響也遠(yuǎn)遠(yuǎn)比悲觀鎖要小
  • 樂觀鎖沒有因競爭而造成的系統(tǒng)上下文切換,所以在性能上更勝一籌

實現(xiàn)原理

  1. CAS是實現(xiàn)樂觀鎖的核心算法,包含3個參數(shù):V(需要更新的變量),E(預(yù)期值)、N(最新值)
  2. 只有V等于E時,V才會被設(shè)置為N
  3. 如果V不等于E了,說明其它線程已經(jīng)更新了V,此時該線程不做操作,返回V的真實值

CAS實現(xiàn)原子操作

AtomicInteger是基于CAS實現(xiàn)的一個線程安全的整型類,Unsafe調(diào)用CPU底層指令實現(xiàn)原子操作

// JAVA.util.concurrent.atomic.AtomicInteger
public final int getAndIncrement() {
 return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndDecrement() {
 return unsafe.getAndAddInt(this, valueOffset, -1);
}
// sun.misc.Unsafe
public final int getAndAddInt(Object o, long offset, int delta) {
 int v;
 do {
 v = getIntVolatile(o, offset);
 } while (!compareAndSwapInt(o, offset, v, v + delta));
 return v;
}
public native int getIntVolatile(Object o, long offset);
public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);

處理器實現(xiàn)原子操作

  1. CAS是調(diào)用處理器底層指令來實現(xiàn)原子操作的
  2. 處理器和物理內(nèi)存之間的通信速度要遠(yuǎn)低于處理器間的處理速度,所以處理器有自己的內(nèi)部緩存(L1/L2/L3)
  3. 服務(wù)器通常為多處理器,并且處理器是多核的,每個處理器維護了一塊字節(jié)的緩存存,每個內(nèi)核也維護了一塊字節(jié)的緩存
  • 此時在多線程并發(fā)就會存在緩存不一致的問題,從而導(dǎo)致數(shù)據(jù)不一致
  1. 處理器提供了總線鎖定緩存鎖定兩種機制來保證復(fù)雜內(nèi)存操作的原子性
  • 總線鎖定
  • 當(dāng)處理器要操作一個共享變量時,會在總線上會發(fā)出一個Lock信號,此時其它處理器就不能操作共享變量了
  • 總線鎖定在阻塞其他處理器獲取該共享變量的操作請求時,也可能會導(dǎo)致大量阻塞,從而增加系統(tǒng)的性能開銷
  • 緩存鎖定(后來出現(xiàn))
  • 當(dāng)某個處理器對緩存中的共享變量進(jìn)行了操作,就會通知其他處理器放棄存儲或者重新讀取該共享變量
  • 目前最新的處理器都支持緩存鎖定機制
Java性能 -- CAS樂觀鎖

 

 

優(yōu)化CAS樂觀鎖

  1. 樂觀鎖在并發(fā)性能上要優(yōu)于悲觀鎖
  • 但在寫大于讀的操作場景下,CAS失敗的可能性增大,如果循環(huán)CAS,會長時間占用CPU
  • 例如上面的AtomicInteger#getAndIncrement
  1. JDK 1.8中,提供了新的原子類LongAdder
  • LongAdder在高并發(fā)場景下會比AtomicInteger和AtomicLong的性能更好,代價是消耗更多的內(nèi)存空間
  • 核心思想:空間換時間
  • 實現(xiàn)原理:降低操作共享變量的并發(fā)數(shù)
  • LongAdder內(nèi)部由一個base變量和一個cell[]數(shù)組組成
  • 當(dāng)只有一個寫線程(沒有競爭
  • LongAdder會直接使用base變量作為原子操作變量,通過CAS操作修改base變量
  • 當(dāng)有多個寫線程(存在競爭
  • 除了占用base變量的一個寫線程外,其他寫線程的value值會分散到cell數(shù)組中
  • 不同線程會命中到數(shù)組的不同槽中,各個線程只對自己槽中的value進(jìn)行CAS操作
  • value=base+∑ni=0Cell[i]
  • LongAdder在操作后的返回值只是一個近似準(zhǔn)確的值,但最終返回的是一個準(zhǔn)確的值
  • LongAdder不適合實時性要求較高的場景

性能對比

 

Java性能 -- CAS樂觀鎖

 

 

  1. 讀大于寫,讀寫鎖ReentrantReadWriteLock、讀寫鎖StampedLock、樂觀鎖LongAdder的性能最好
  2. 寫大于讀,樂觀鎖的性能最好,其他四種鎖的性能差不多
  3. 讀約等于寫,兩種讀寫鎖和樂觀鎖的性能要優(yōu)于synchronized和Lock

小結(jié)

  1. 樂觀鎖的常見使用場景:數(shù)據(jù)庫更新
  • 為每條數(shù)據(jù)定義一個版本號,在更新前獲取版本號,在更新數(shù)據(jù)時,再判斷版本號是否被更新過,如果沒有才更新數(shù)據(jù)
  1. CAS樂觀鎖的使用比較受限,因為樂觀鎖只能保證單個變量操作的原子性
  2. CAS樂觀鎖在高并發(fā)寫大于讀的場景下
  • 大部分線程的原子操作會失敗,失敗后的線程將不斷重試CAS原子操作,導(dǎo)致大量線程長時間占用CPU資源
  • JDK 1.8中,新增了原子類LongAdder,采用空間換時間的思路解決了這個問題,但實時性不高

分享到:
標(biāo)簽:樂觀 Java CAS
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運動步數(shù)有氧達(dá)人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定