欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
并發(fā)策略-CAS算法

  對于并發(fā)控制而言,我們平時(shí)用的鎖(synchronized,Lock)是一種悲觀(guān)的策略。它總是假設每一次臨界區操作會(huì )產(chǎn)生沖突,因此,必須對每次操作都小心翼翼。如果多個(gè)線(xiàn)程同時(shí)訪(fǎng)問(wèn)臨界區資源,就寧可犧牲性能讓線(xiàn)程進(jìn)行等待,所以鎖會(huì )阻塞線(xiàn)程執行。

  與之相對的有一種樂(lè )觀(guān)的策略,它會(huì )假設對資源的訪(fǎng)問(wèn)是沒(méi)有沖突的。既然沒(méi)有沖突也就無(wú)需等待了,所有的線(xiàn)程都在不停頓的狀態(tài)下持續執行。那如果遇到問(wèn)題了無(wú)鎖的策略使用一種叫做比較交換(CAS Compare And Swap)來(lái)鑒別線(xiàn)程沖突,一旦檢測到?jīng)_突產(chǎn)生,就重試當前操作直到?jīng)]有沖突。CAS算法是非阻塞的,它對死鎖問(wèn)題天生免疫,而且它比基于鎖的方式擁有更優(yōu)越的性能。

  CAS算法的過(guò)程是這樣:它包含三個(gè)參數 CAS(V,E,N)。V表示要更新的變量,E表示預期的值,N表示新值。僅當V值等于E值時(shí),才會(huì )將V的值設置成N,否則什么都不做。最后CAS返回當前V的值。CAS算法需要你額外給出一個(gè)期望值,也就是你認為現在變量應該是什么樣子,如果變量不是你想象的那樣,那說(shuō)明已經(jīng)被別人修改過(guò)。你就重新讀取,再次嘗試修改即可。

  JDK并發(fā)包有一個(gè)atomic包,里面實(shí)現了一些直接使用CAS操作的線(xiàn)程安全的類(lèi)型。其中最常用的一個(gè)類(lèi)應該就是AtomicInteger。我們以此為例來(lái)研究一下沒(méi)有鎖的情況下如何做到線(xiàn)程安全。

private volatile int value;

  這是AtomicInteger類(lèi)的核心字段,代表當前實(shí)際取值,借助volatile保證線(xiàn)程間數據的可見(jiàn)性。

  獲取內部數據的方法:

  public final int get() {        return value;    }

  我們關(guān)注一下incrementAndGet()的內部實(shí)現  

1  public final int incrementAndGet() {2         for (;;) {3             int current = get();4             int next = current + 1;5             if (compareAndSet(current, next))6                 return next;7         }8     }

 

  代碼第二行使用了一個(gè)死循環(huán),原因是:CAS的操作未必都是成功的,因此對于不成功的情況,我們就需要進(jìn)行不斷的嘗試。第三行取得當前值,接著(zhù)+1得到新值next。這里我們使用CAS必需的兩個(gè)參數:期望值以及新值。使用compareAndSet()將新值next寫(xiě)入。成功的條件是在寫(xiě)入的時(shí)刻,當前的值應該要等于剛剛取到的current。如果不是這樣則說(shuō)明AtomicInteger的值在第3行到第5行之間被其他線(xiàn)程修改過(guò)了。當前看到的狀態(tài)是一個(gè)過(guò)期的狀態(tài),因此返回失敗,需要進(jìn)行下一次重試,知道成功為止。

    public final boolean compareAndSet(int expect, int update) {        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);    }

  整體的過(guò)程就是這樣子的,利用CPU的CAS指令,同時(shí)借助JNI來(lái)完成Java的非阻塞算法。其它原子操作都是利用類(lèi)似的特性完成的。大概的邏輯應該是這樣:

if (this == expect) {    this = update    return true;} else {    return false;} 

  CAS雖然能高效的解決原子問(wèn)題,但是CAS也會(huì )帶來(lái)1個(gè)經(jīng)典問(wèn)題即ABA問(wèn)題:

  因為CAS需要在操作值的時(shí)候檢查下值有沒(méi)有發(fā)生變化,如果沒(méi)有發(fā)生變化則更新,但是如果一個(gè)值原來(lái)是A,變成了B,又變成了A,那么使用CAS進(jìn)行檢查時(shí)會(huì )發(fā)現它的值沒(méi)有發(fā)生變化,但是實(shí)際上卻變化了。

  ABA問(wèn)題的解決思路就是使用版本號。在變量前面追加上版本號,每次變量更新的時(shí)候把版本號加一,那么A-B-A 就會(huì )變成1A-2B-3A。

  從Java1.5開(kāi)始JDK的atomic包里提供了一個(gè)類(lèi)AtomicStampedReference來(lái)解決ABA問(wèn)題。這個(gè)類(lèi)在內部不僅維護了對象值,還維護了一個(gè)時(shí)間戳(可以是任意的一個(gè)整數來(lái)表示狀態(tài)值)。當設置對象值時(shí),對象值和狀態(tài)值都必須滿(mǎn)足期望值才會(huì )寫(xiě)入成功。因此即使對象被反復讀寫(xiě),寫(xiě)會(huì )原值,只要狀態(tài)值發(fā)生變化,就能防止不恰當的寫(xiě)入?! ?/p>

/**
* @param expectedReference 期望值
* @param newReference 寫(xiě)入新值
* @param expectedStamp 期望狀態(tài)值
* @param newStamp 新?tīng)顟B(tài)值
* @return true if successful
*/

public
boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) { Pair<V> current = pair; return expectedReference == current.reference && expectedStamp == current.stamp && ((newReference == current.reference && newStamp == current.stamp) || casPair(current, Pair.of(newReference, newStamp))); }

 

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
面試???--- CAS
樂(lè )觀(guān)鎖的一種實(shí)現方式——CAS
【死磕Java并發(fā)】—-深入分析CAS
Java多核線(xiàn)程筆記
舒の隨想日記 » 用AtomicStampedReference解決ABA問(wèn)題
java.util.concurrent系列文章--(4)非阻塞算法簡(jiǎn)介 - 線(xiàn)程及并發(fā)處...
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久