成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

悲觀鎖和樂觀鎖以及CAS機(jī)制

levius / 1258人閱讀

摘要:加鎖才能保證線程安全使用之后,不加鎖,也是線程安全的。確保不出現(xiàn)線程安全問題。一般在數(shù)據(jù)庫中使用樂觀鎖都會拿版本號作為對比值,因為版本號會一直增加,沒有重復(fù)的,所以不會出現(xiàn)這個問題。

悲觀鎖:

認(rèn)為每次獲取數(shù)據(jù)的時候數(shù)據(jù)一定會被人修改,所以它在獲取數(shù)據(jù)的時候會把操作的數(shù)據(jù)給鎖住,這樣一來就只有它自己能夠操作,其他人都堵塞在那里。

樂觀鎖:

認(rèn)為每次獲取數(shù)據(jù)的時候數(shù)據(jù)不會被別人修改,所以獲取數(shù)據(jù)的時候并沒有鎖住整個數(shù)據(jù),但是在更新的時候它會去判斷一下要更新的數(shù)據(jù)有沒有被別人修改過,例如更新前查詢該數(shù)據(jù)的版本號,更新的時候看看該版本號有沒有被人修改過,如果被人修改過了,那就不會去更新。

應(yīng)用場景:

悲觀鎖:
因為悲觀鎖會鎖住數(shù)據(jù),讓其他人都等待,所以當(dāng)一個系統(tǒng)并發(fā)量不大,而且可以接收一定延遲的時候可以選擇悲觀鎖。
樂觀鎖:
因為樂觀鎖會在更新前去查數(shù)據(jù),所以比較適合讀多少寫的場景,因為寫操作多的話會造成大量的查詢操作,給系統(tǒng)帶來壓力。例如SVN、Git等版本控制管理器就是應(yīng)用的樂觀鎖,當(dāng)你提交數(shù)據(jù)的時候?qū)Ρ认掳姹咎?,如果遠(yuǎn)程倉庫的版本號和本地的不一樣就表示有人已經(jīng)提交過代碼了,你需要先更新代碼到本地處理一下版本沖突問題,不然是沒有辦法提交的。

CAS:

CAS是Compare And Set的縮寫,中文意思就是比較和操作,是一個非阻塞算法。它其實是一個CPU的指令,它會拿內(nèi)存值和一個給定的值進(jìn)行比較,如果相等的話就會把內(nèi)存值更新為另一個給定的值。其實CAS就是使用一個樂觀鎖的機(jī)制。

Java中CAS機(jī)制的應(yīng)用:

從JDK1.5開始java.util.concurrent.atomic包中新增了一些原子類,AtomicInteger、AtomicLong等等,就是專門解決高并發(fā)下的同步問題。因為類似i++、++i的操作不是線程安全的,以前我們都會使用Synchronized關(guān)鍵字,但是現(xiàn)在我們直接使用這些原子類就可以解決線程安全的問題。下面用代碼來看看有什么變化。

class Test1 {
    private volatile int count = 0;

    public synchronized void increment() {
    //加鎖才能保證線程安全
        count++; 
    }

    public int getCount() {
        return count;
    }
}

class Test2 {
    private AtomicInteger count = new AtomicInteger();

    //使用AtomicInteger之后,不加鎖,也是線程安全的。
    public void increment() {
        count.incrementAndGet();
    }
   
    public int getCount() {
        return count.get();
    }
}

下面這些是AtomicInteger提供的別的方法。

//獲取當(dāng)前的值
public final int get() 
//獲取當(dāng)前的值,并設(shè)置新的值
public final int getAndSet(int newValue)
//獲取當(dāng)前的值,并自增
public final int getAndIncrement()
//獲取當(dāng)前的值,并自減
public final int getAndDecrement() 
//獲取當(dāng)前的值,并加上預(yù)期的值
public final int getAndAdd(int delta) 

我們從源碼的角度看看AtomicInteger是怎么實現(xiàn)CAS機(jī)制的。unsafe是java提供的用來獲取對象內(nèi)存地址的類,作用是在更新操作時提供“比較并替換”的作用。valueOffset是記錄value本身在內(nèi)存的地址,value被聲明為volatile是保證在更新操作時,當(dāng)前線程可以拿到value最新的值。

public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    // setup to use Unsafe.compareAndSwapInt for updates
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    private volatile int value;

比如incrementAndGet方法,是獲取當(dāng)前的值并自增。

public final int incrementAndGet() {
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}

我們進(jìn)getAndAddInt方法看看,getIntVolatile和compareAndSwapInt都是本地方法,就是通過本地方法來實現(xiàn)CAS機(jī)制。確保不出現(xiàn)線程安全問題。

public final int getAndSetInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var4));
        return var5;
    }
    
    
 public native int getIntVolatile(Object var1, long var2);
 public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

CAS可能會引起的問題

因為CAS并不會鎖住數(shù)據(jù)讓其他線程阻塞,所以實際上是自旋鎖的原理。自旋鎖就是當(dāng)線程獲取鎖的時候發(fā)現(xiàn)這個鎖已經(jīng)被別的線程搶了,它不是阻塞自己,而是一直循環(huán)查看這個鎖有沒有被釋放,這就叫自旋鎖。因為一直循環(huán)查看所以可以能會造成CPU負(fù)擔(dān)過重,最好設(shè)置參數(shù)限制查看鎖的次數(shù)。

死鎖問題,有一個線程拿到自旋鎖之后,又去拿鎖,例如遞歸的時候會出現(xiàn)這樣的情況,自己等待自己釋放縮,卡在那里不動。

ABA問題,這個問題就是說當(dāng)線程1讀到內(nèi)存值為A,然后線程2進(jìn)來了把內(nèi)存值改為B,然后又改為了A,這個時候線程1覺得沒有問題,就更新了。一般在數(shù)據(jù)庫中使用樂觀鎖都會拿版本號作為對比值,因為版本號會一直增加,沒有重復(fù)的,所以不會出現(xiàn)這個問題。Java中也提供了AtomicStampedReference這個類,大致原理也是提供一個版本號來對比。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/69110.html

相關(guān)文章

  • 不可不說的Java“”事

    摘要:本文旨在對鎖相關(guān)源碼本文中的源碼來自使用場景進(jìn)行舉例,為讀者介紹主流鎖的知識點,以及不同的鎖的適用場景。中,關(guān)鍵字和的實現(xiàn)類都是悲觀鎖。自適應(yīng)意味著自旋的時間次數(shù)不再固定,而是由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態(tài)來決定。 前言 Java提供了種類豐富的鎖,每種鎖因其特性的不同,在適當(dāng)?shù)膱鼍跋履軌蛘宫F(xiàn)出非常高的效率。本文旨在對鎖相關(guān)源碼(本文中的源碼來自JDK 8)、使用場景...

    galaxy_robot 評論0 收藏0
  • CAS 算法 —— Compare and Swap

    摘要:算法算法會先對一個內(nèi)存變量位置和一個給定的值進(jìn)行比較,如果相等,則用一個新值去修改這個內(nèi)存變量位置。因為是非公平鎖,所以一上來就嘗試搶占鎖給定舊值并希望用新值去更新內(nèi)存變量。 本文翻譯和原創(chuàng)各占一半,所以還是厚顏無恥歸類到原創(chuàng)好了...https://howtodoinjava.com/jav...java 5 其中一個令人振奮的改進(jìn)是新增了支持原子操作的類型,例如 AtomicInt...

    mmy123456 評論0 收藏0
  • Java中的以及sychronized實現(xiàn)機(jī)制

    摘要:有可能,會造成優(yōu)先級反轉(zhuǎn)或者饑餓現(xiàn)象。悲觀鎖在中的使用,就是利用各種鎖。對于而言,其是獨享鎖。偏向鎖,顧名思義,它會偏向于第一個訪問鎖的線程,大多數(shù)情況下鎖不僅不存在多線程競爭,而且總是由同一線程多次獲得。 理解鎖的基礎(chǔ)知識 如果想要透徹的理解java鎖的來龍去脈,需要先了解以下基礎(chǔ)知識。 基礎(chǔ)知識之一:鎖的類型 按照其性質(zhì)分類 公平鎖/非公平鎖 公平鎖是指多個線程按照申請鎖的順序來獲...

    linkin 評論0 收藏0
  • Spring Boot+SQL/JPA實戰(zhàn)悲觀樂觀

    摘要:所以悲觀鎖是限制其他線程,而樂觀鎖是限制自己,雖然他的名字有鎖,但是實際上不算上鎖,只是在最后操作的時候再判斷具體怎么操作。悲觀鎖和樂觀鎖比較悲觀鎖適合寫多讀少的場景。 最近在公司的業(yè)務(wù)上遇到了并發(fā)的問題,并且還是很常見的并發(fā)問題,算是低級的失誤了。由于公司業(yè)務(wù)相對比較復(fù)雜且不適合公開,在此用一個很常見的業(yè)務(wù)來還原一下場景,同時介紹悲觀鎖和樂觀鎖是如何解決這類并發(fā)問題的。 公司業(yè)務(wù)就是...

    Keven 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<