国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

悲觀鎖和樂觀鎖以及CAS機制

levius / 1215人閱讀

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

悲觀鎖:

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

樂觀鎖:

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

應用場景:

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

CAS:

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

Java中CAS機制的應用:

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

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提供的別的方法。

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

我們從源碼的角度看看AtomicInteger是怎么實現CAS機制的。unsafe是java提供的用來獲取對象內存地址的類,作用是在更新操作時提供“比較并替換”的作用。valueOffset是記錄value本身在內存的地址,value被聲明為volatile是保證在更新操作時,當前線程可以拿到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方法,是獲取當前的值并自增。

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

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

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并不會鎖住數據讓其他線程阻塞,所以實際上是自旋鎖的原理。自旋鎖就是當線程獲取鎖的時候發現這個鎖已經被別的線程搶了,它不是阻塞自己,而是一直循環查看這個鎖有沒有被釋放,這就叫自旋鎖。因為一直循環查看所以可以能會造成CPU負擔過重,最好設置參數限制查看鎖的次數。

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69110.html

相關文章

  • 不可不說的Java“”事

    摘要:本文旨在對鎖相關源碼本文中的源碼來自使用場景進行舉例,為讀者介紹主流鎖的知識點,以及不同的鎖的適用場景。中,關鍵字和的實現類都是悲觀鎖。自適應意味著自旋的時間次數不再固定,而是由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態來決定。 前言 Java提供了種類豐富的鎖,每種鎖因其特性的不同,在適當的場景下能夠展現出非常高的效率。本文旨在對鎖相關源碼(本文中的源碼來自JDK 8)、使用場景...

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

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

    mmy123456 評論0 收藏0
  • Java中的以及sychronized實現機制

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

    linkin 評論0 收藏0
  • Spring Boot+SQL/JPA實戰悲觀樂觀

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

    Keven 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<