91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

高級并發編程系列之什么是原子類

發布時間:2021-10-23 15:36:55 來源:億速云 閱讀:148 作者:iii 欄目:編程語言

本篇內容介紹了“高級并發編程系列之什么是原子類”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

1.考考你

相信作為資深程序員的你,對于AtomicInteger這樣的類,即以Atomic開始的類一定不會感到陌生。我們在翻看很多框架源碼、或者第三方組件都會經常看到它們,如影隨形。

那么問題來了,像Atomicxxx這樣的類,到底是什么意思呢?從字面意思比較好理解,Atomic即原子性,那么Atomicxxx即原子類。講到這里,你一定還記得我們說過線程安全的三個基本要素,我們一起來回顧一下:可見性、原子性、有序性。原子類的原子性,講的就是這個原子性,于是你可以先記住一個結論:原子類,它是線程安全的類

到這里有朋友可能會提出質疑:你說線程安全,就線程安全嗎?我不服,你沒有講清楚。我不聽,我不聽......好吧,看官們莫急,且聽我一步一步分析,娓娓道來,話說......

#考考你:
1.你真的理解原子類的核心思想嗎
2.你在你的項目中,有直接用到過原子類嗎

2.案例

2.1.自增操作案例

2.1.1.普通變量版本

案例描述:

  • 定義一個普通的int型變量value,初始值為:0

  • 開啟兩個線程thread_1,thread_2并行執行value++操作

  • 每個線程執行 5000次,預期執行結果: 2 * 5000 = 10000次

  • 通過觀察最終執行結果,是否等于預期10000次

  • 結果不相等,說明線程不安全,原因是:value++操作不是一個原子性操作

package com.anan.edu.common.newthread.atomic;

/**
 * 普通 int變量 ++ 操作,非原子性,線程不安全
 *
 * @author ThinkPad
 * @version 1.0
 * @date 2020/11/29 8:27
 */
public class CommonIntDemo {

    /**
     * 普通成員變量
     */
    private int value = 0;

    public  void addValue(){
        value++;
    }

    public static void main(String[] args) throws InterruptedException {
        // 1.創建CommonIntDemo對象
        CommonIntDemo demo = new CommonIntDemo();

        // 2.創建2兩個線程,每個線程調用方法addValue 5000次
        // 預期value值結果等于:2 * 5000 = 10000
        int loopEnd = 5000;
        Thread thread_1 = new Thread(() -> {
            for(int i = 0; i < loopEnd; i++){
                demo.addValue();
            }
        }, "thread_1");

        Thread thread_2 = new Thread(() -> {
            for(int i = 0; i < loopEnd; i++){
                demo.addValue();
            }
        }, "thread_2");

        // 3.啟動執行線程
        thread_1.start();
        thread_2.start();

        // 4.主線程等待子線程執行完成,打印value值
        thread_1.join();
        thread_2.join();

        System.out.println("int型成員變量value最終結果:" + demo.value);
    }
}

執行結果分析:

高級并發編程系列之什么是原子類

2.1.2.AtomicInteger版本

案例描述:

  • 定義一個AtomicInteger變量value,初始值為:0

  • 開啟兩個線程thread_1,thread_2并行執行value.incrementAndGet()操作

  • 每個線程執行 5000次,預期執行結果: 2 * 5000 = 10000次

  • 通過觀察最終執行結果,是否等于預期10000次

  • 結果相等,說明線程安全,原因是:原子類同時滿足了可見性、與原子性

package com.anan.edu.common.newthread.atomic;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 原子類AtomicInteger,實現自增操作,線程安全
 *
 * @author ThinkPad
 * @version 1.0
 * @date 2020/11/29 8:27
 */
public class AtomicIntegerDemo {

    /**
     * AtomicInteger成員變量
     */
    private AtomicInteger value = new AtomicInteger(0);

    public  void addValue(){
        value.incrementAndGet();
    }

    public static void main(String[] args) throws InterruptedException {
        // 1.創建AtomicIntegerDemo對象
        AtomicIntegerDemo demo = new AtomicIntegerDemo();

        // 2.創建2兩個線程,每個線程調用方法addValue 5000次
        // 預期value值結果等于:2 * 5000 = 10000
        int loopEnd = 5000;
        Thread thread_1 = new Thread(() -> {
            for(int i = 0; i < loopEnd; i++){
                demo.addValue();
            }
        }, "thread_1");

        Thread thread_2 = new Thread(() -> {
            for(int i = 0; i < loopEnd; i++){
                demo.addValue();
            }
        }, "thread_2");

        // 3.啟動執行線程
        thread_1.start();
        thread_2.start();

        // 4.主線程等待子線程執行完成,打印value值
        thread_1.join();
        thread_2.join();

        System.out.println("AtomicInteger型成員變量value最終結果:" + demo.value);
    }
}

執行結果分析:

高級并發編程系列之什么是原子類

2.2.原子類底層原理分析

2.2.1.再次分析線程安全核心思想

通過比較普通類型int型變量自增操作,與原子型AtomicInteger型變量自增操作。我們看到應用層代碼幾乎沒有差異,僅僅是通過AtomicInteger替換int實現自增操作,即保證了線程安全。那么AtomicInteger它是如何做到的呢?

要分析清楚AtomicInteger底層原理,還需要回到我們說過的線程安全基本要素:可見性、原子性、有序性。就是說不管通過什么手段,要實現線程安全,一定要滿足這三個基本要素,換句話說,滿足了三個基本要素,也即實現了線程安全。

那么我們就從這三個要素開始分析。首先看最容易理解的有序性,你還記得什么是有序性嗎?它是說線程內有序,線程之間無序。有序性比較好理解,我們就不過多解釋了。

再來看可見性,同樣你還記得什么是可見性嗎?我們知道jmm內存模型,每個線程都有自己的私人空間(工作內存),所有線程共享公共空間(主內存)。那么如果要保證某個變量在線程間的可見性,即當線程A操作該變量后,需要同步將變量值從私人空間同步到公共空間:工作內存--->主內存;同理其它線程在操作變量前,需要從公共空間將變量值同步到私人空間:主內存--->工作內存。java編程語法上給我們提供了一個關鍵字:volatile。用于實現可見性。你可能還需要下面這個圖:

高級并發編程系列之什么是原子類

最后再來看原子性,原子性你應該還記得,我們上一篇:高級并發編程系列十二(一文搞懂cas)剛剛分享過。cas本質上是不到黃河心不死,什么意思呢?即是不釋放cpu,循環操作,直到操作成功為止。我們是這么解釋的,你也應該還記得對吧。而且我們還說過對于cas,它的操作原理是三個值:內存值A、期望值B、更新值C。每次操作都會比較內存值A,是否等于期望值B、如果等于則將內存值更新成值C,操作成功;如果內存值A,不等于期望值B,則操作失敗,進行下一次循環操作。你可能還需要下面這個圖:

高級并發編程系列之什么是原子類

好了到這里,我們可以一起來看AtomicInteger的源碼了。看看是否滿足我們說的可見性、原子性。進一步分析清楚AtomicInteger類線程安全的實現原理。下面我們通過截圖+文字描述的方式,方便你理解。

2.2.2.AtomicInteger類聲明

先來看AtomicInteger類的聲明,這一塊對于不熟悉的朋友可能比較難看懂,我們先截圖看一下。

高級并發編程系列之什么是原子類

2.2.3.方法incrementAndGet分析

通過類聲明部分源碼,我們看到線程安全的可見性,通過volatile關鍵字修飾value成員變量,已經有了保障。那么原子性,又是如何保障的呢?答案是通過Unsafe工具類,進行cas操作來保障的。看圖:

高級并發編程系列之什么是原子類

2.3.juc原子類分類

相信通過上面的分析,你已經理解了原子類線程安全的底層實現原理,如果你理解起來稍微還有點難度,我建議你多看兩遍。對于一個程序員來說,我們不應該只會用用框架,底層思想和原理才是內功。

那么關于原子類的底層分析,我們暫時放一放,下面我們一起來看一下juc包中提供的常見原子能力工具類。它們每一個的底層原理,都在上面分析過了,我就不再逐一分析了,只是簡單的列舉出來,如果你感興趣的話,可以找一兩個按照我上面的分析思路,自己分析一下,應該會有意想不到的驚喜!

  • 基本原子類,代表:AtomicInteger、AtomicLong

  • 數組原子類,代表:AtomicIntegerArray、AtomicLongArray

  • 引用原子類,代表:AtomicReference<V>。關于引用原子類,稍微加一句:它可以把一個普通對象,包裝成具有原子能力的對象

  • 提供升級能力原子類,代表:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater

  • 累加器原子類,代表:LongAdder。關于累加器,稍微多加一句:它是jdk1.8開始后新加入的小伙伴,性能比起AtomicLong來說杠杠的。

“高級并發編程系列之什么是原子類”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

自治县| 莎车县| 龙里县| 闽侯县| 自贡市| 盱眙县| 甘孜| 岑溪市| 油尖旺区| 叙永县| 屏东市| 体育| 连州市| 东港市| 丹巴县| 安溪县| 义马市| 黑河市| 徐闻县| 瑞丽市| 申扎县| 同德县| 黄浦区| 石河子市| 陵川县| 遂溪县| 唐海县| 枞阳县| 云和县| 大余县| 法库县| 曲阳县| 平凉市| 株洲县| 泰和县| 澎湖县| 洪雅县| 临颍县| 青神县| 始兴县| 襄城县|