欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java多線程之原子類解析

 更新時間:2023年10月24日 08:47:38   作者:假裝你是大灰狼  
這篇文章主要介紹了Java多線程之原子類解析,Java原子類是一種多線程編程中常用的工具,用于實(shí)現(xiàn)線程安全的操作,它們提供了一種原子性操作的機(jī)制,確保多個線程同時訪問共享變量時的數(shù)據(jù)一致性,需要的朋友可以參考下

前言

Java提供的原子類是靠 sun 基于 CAS 實(shí)現(xiàn)的,CAS 是一種樂觀鎖。

原子變量類相當(dāng)于一種泛化的 volatile 變量,能夠支持原子的和有條件的讀-改-寫操作。AtomicInteger 表示一個int類型的值,并提供了 get 和 set 方法,這些 Volatile 類型的int變量在讀取和寫入上有著相同的內(nèi)存語義。它還提供了一個原子的 compareAndSet 方法(如果該方法成功執(zhí)行,那么將實(shí)現(xiàn)與讀取/寫入一個 volatile 變量相同的內(nèi)存效果),以及原子的添加、遞增和遞減等方法。AtomicInteger 表面上非常像一個擴(kuò)展的 Counter 類,但在發(fā)生競爭的情況下能提供更高的可伸縮性,因?yàn)樗苯永昧擞布Σl(fā)的支持。

AtomicInteger的實(shí)現(xiàn)

AtomicInteger 是一個支持原子操作的 Integer 類,就是保證對 AtomicInteger 類型變量的增加和減少操作是原子性的,不會出現(xiàn)多個線程下的數(shù)據(jù)不一致問題。如果不使用 AtomicInteger,要實(shí)現(xiàn)一個按順序獲取的 ID,就必須在每次獲取時進(jìn)行加鎖操作,以避免出現(xiàn)并發(fā)時獲取到同樣的 ID 的現(xiàn)象。

接下來通過源代碼來看 AtomicInteger 具體是如何實(shí)現(xiàn)的原子操作。

首先看 value 的聲明:

private volatile int value;

volatile 修飾的 value 變量,保證了變量的可見性。

incrementAndGet() 方法,下面是具體的代碼:

public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}

通過源碼,可以知道,這個方法的做法為先獲取到當(dāng)前的 value 屬性值,然后將 value 加 1,賦值給一個局部的 next 變量,然而,這兩步都是非線程安全的,但是內(nèi)部有一個死循環(huán),不斷去做 compareAndSet 操作,直到成功為止,也就是修改的根本在 compareAndSet 方法里面,compareAndSet()方法的代碼如下:

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

compareAndSet()方法調(diào)用的compareAndSwapInt()方法的聲明如下,是一個native方法。

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, intvar5);

compareAndSet 傳入的為執(zhí)行方法時獲取到的 value 屬性值,next 為加 1 后的值, compareAndSet 所做的為調(diào)用 Sun 的 UnSafe 的 compareAndSwapInt 方法來完成,此方法為 native 方法,compareAndSwapInt 基于的是 CPU 的 CAS 指令來實(shí)現(xiàn)的。所以基于 CAS 的操作可認(rèn)為是無阻塞的,一個線程的失敗或掛起不會引起其它線程也失敗或掛起。并且由于 CAS 操作是 CPU 原語,所以性能比較好。

類似的,還有 decrementAndGet() 方法。它和 incrementAndGet() 的區(qū)別是將 value 減 1,賦值給next 變量。

AtomicInteger 中還有 getAndIncrement() 和 getAndDecrement() 方法,他們的實(shí)現(xiàn)原理和上面的兩個方法完全相同,區(qū)別是返回值不同,前兩個方法返回的是改變之后的值,即 next。而這兩個方法返回的是改變之前的值,即 current。還有很多的其他方法,就不列舉了。

CAS算法

CAS(Compare-And-Swap)算法保證數(shù)據(jù)操作的原子性。

CAS 算法是硬件對于并發(fā)操作共享數(shù)據(jù)的支持。

CAS 包含了三個操作數(shù):

  • 內(nèi)存值 V
  • 預(yù)估值 A
  • 更新值 B

當(dāng)且僅當(dāng) V == A 時,V 將被賦值為 B,否則循環(huán)著不斷進(jìn)行判斷 V 與 A 是否相等。

關(guān)于樂觀鎖與悲觀鎖

樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數(shù)據(jù)的時候都認(rèn)為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù),可以使用版本號等機(jī)制。樂觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫如果提供類似于write_condition機(jī)制的其實(shí)都是提供的樂觀鎖。

CAS便是樂觀鎖技術(shù),當(dāng)多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程并不會被掛起,而是被告知這次競爭中失敗,并可以再次嘗試。

CAS有3個操作數(shù),內(nèi)存值V,舊的預(yù)期值A(chǔ),要修改的新值B。當(dāng)且僅當(dāng)預(yù)期值A(chǔ)和內(nèi)存值V相同時,將內(nèi)存值V修改為B,否則什么都不做。

悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數(shù)據(jù)的時候都認(rèn)為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會block直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。

比如說synchronized就是一種獨(dú)占鎖,他假設(shè)最壞的情況,并且只有在確保其它線程不會造成干擾的情況下執(zhí)行,會導(dǎo)致其它所有需要鎖的線程掛起,等待持有鎖的線程釋放鎖。

缺點(diǎn):

由于在進(jìn)程掛起和恢復(fù)執(zhí)行過程中存在著很大的開銷。當(dāng)一個線程正在等待鎖時,它不能做任何事。舉個栗子,如果一個線程需要某個資源,但是這個資源的占用時間很短,當(dāng)線程第一次搶占這個資源時,可能這個資源被占用,如果此時掛起這個線程,可能立刻就發(fā)現(xiàn)資源可用,然后又需要花費(fèi)很長的時間重新?lián)屨兼i,時間代價就會非常的高。

到此這篇關(guān)于Java多線程之原子類解析的文章就介紹到這了,更多相關(guān)Java原子類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中easypoi導(dǎo)入excel文件列名相同的處理方案

    Java中easypoi導(dǎo)入excel文件列名相同的處理方案

    這篇文章主要介紹了Java中easypoi導(dǎo)入excel文件列名相同的處理方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 分布式事務(wù)CAP兩階段提交及三階段提交詳解

    分布式事務(wù)CAP兩階段提交及三階段提交詳解

    這篇文章主要為大家介紹了分布式事務(wù)CAP、兩階段提交及三階段提交的內(nèi)容詳解有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-01-01
  • Java反射機(jī)制基礎(chǔ)詳解

    Java反射機(jī)制基礎(chǔ)詳解

    這篇文章主要介紹了JAVA 反射機(jī)制的相關(guān)知識,文中講解的非常細(xì)致,代碼幫助大家更好的理解學(xué)習(xí),感興趣的朋友可以了解下,希望能給你帶來幫助
    2021-08-08
  • Java實(shí)現(xiàn)簡易俄羅斯方塊

    Java實(shí)現(xiàn)簡易俄羅斯方塊

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡易俄羅斯方塊,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • springboot配置文件中屬性變量引用方式@@解讀

    springboot配置文件中屬性變量引用方式@@解讀

    這篇文章主要介紹了springboot配置文件中屬性變量引用方式@@解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • java環(huán)境搭建教程

    java環(huán)境搭建教程

    這篇文章主要為大家詳細(xì)介紹了java環(huán)境的搭建教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 使用spring?jpa?如何給外鍵賦值

    使用spring?jpa?如何給外鍵賦值

    這篇文章主要介紹了使用spring?jpa?如何給外鍵賦值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 解讀@RequestBody與post請求的關(guān)系

    解讀@RequestBody與post請求的關(guān)系

    這篇文章主要介紹了解讀@RequestBody與post請求的關(guān)系,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • mybatis-generator如何自定義注釋生成

    mybatis-generator如何自定義注釋生成

    這篇文章主要介紹了mybatis-generator如何自定義注釋生成的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Spring AI 使用本地 Ollama Embeddings的操作方法

    Spring AI 使用本地 Ollama Embeddings的操作方法

    使用 OpenAI 的 Embeddings 接口是有費(fèi)用的,如果想對大量文檔進(jìn)行測試,使用本地部署的 Embeddings 就能省去大量的費(fèi)用,所以我們嘗試使用本地的 Ollama Embeddings,這篇文章主要介紹了Spring AI 使用本地 Ollama Embeddings,需要的朋友可以參考下
    2024-05-05

最新評論