一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - JAVA教程 - Java多線程Atomic包操作原子變量與原子類詳解

Java多線程Atomic包操作原子變量與原子類詳解

2021-02-18 12:47vernonzheng JAVA教程

這篇文章主要介紹了Java多線程Atomic包操作原子變量與原子類詳解,簡單介紹了Atomic,同時涉及java.util.concurrent中的原子變量,Atomic類的作用等相關內容,具有一定參考價值,需要的朋友可以了解下。

在閱讀這篇文章之前,大家可以先看下Java多線程atomic包介紹及使用方法,了解atomic包的相關內容。

一、何謂Atomic

Atomic一詞跟原子有點關系,后者曾被人認為是最小物質的單位。計算機中的Atomic是指不能分割成若干部分的意思。如果一段代碼被認為是Atomic,則表示這段代碼在執行過程中,是不能被中斷的。通常來說,原子指令由硬件提供,供軟件來實現原子方法(某個線程進入該方法后,就不會被中斷,直到其執行完成)

在x86平臺上,CPU提供了在指令執行期間對總線加鎖的手段。CPU芯片上有一條引線#HLOCKpin,如果匯編語言的程序中在一條指令前面加上前綴"LOCK",經過匯編以后的機器代碼就使CPU在執行這條指令的時候把#HLOCKpin的電位拉低,持續到這條指令結束時放開,從而把總線鎖住,這樣同一總線上別的CPU就暫時不能通過總線訪問內存了,保證了這條指令在多處理器環境中的原子性。

二、java.util.concurrent中的原子變量

無論是直接的還是間接的,幾乎java.util.concurrent包中的所有類都使用原子變量,而不使用同步。類似ConcurrentLinkedQueue的類也使用原子變量直接實現無等待算法,而類似ConcurrentHashMap的類使用ReentrantLock在需要時進行鎖定。然后,ReentrantLock使用原子變量來維護等待鎖定的線程隊列。

如果沒有JDK5.0中的JVM改進,將無法構造這些類,這些改進暴露了(向類庫,而不是用戶類)接口來訪問硬件級的同步原語。然后,java.util.concurrent中的原子變量類和其他類向用戶類公開這些功能

java.util.concurrent.atomic的原子類

這個包里面提供了一組原子類。其基本的特性就是在多線程環境下,當有多個線程同時執行這些類的實例包含的方法時,具有排他性,即當某個線程進入方法,執行其中的指令時,不會被其他線程打斷,而別的線程就像自旋鎖一樣,一直等到該方法執行完成,才由JVM從等待隊列中選擇一個另一個線程進入,這只是一種邏輯上的理解。實際上是借助硬件的相關指令來實現的,不會阻塞線程(或者說只是在硬件級別上阻塞了)。其中的類可以分成4組

AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference 
AtomicIntegerArray,AtomicLongArray 
AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater 
AtomicMarkableReference,AtomicStampedReference,AtomicReferenceArray 

其中AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference是類似的。

首先AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference內部api是類似的:舉個AtomicReference的例子

使用AtomicReference創建線程安全的堆棧

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class LinkedStack<T> {
    private AtomicReference<Node<T>> stacks = new AtomicReference<Node<T>>();
    public T push(T e) {
        Node<T> oldNode, newNode;
        while (true) {
            //這里的處理非常的特別,也是必須如此的。
            oldNode = stacks.get();
            newNode = new Node<T>(e, oldNode);
            if (stacks.compareAndSet(oldNode, newNode)) {
                return e;
            }
        }
    }
    public T pop() {
        Node<T> oldNode, newNode;
        while (true) {
            oldNode = stacks.get();
            newNode = oldNode.next;
            if (stacks.compareAndSet(oldNode, newNode)) {
                return oldNode.object;
            }
        }
    }
    private static final class Node<T> {
        private T object;
        private Node<T> next;
        private Node(T object, Node<T> next) {
            this.object = object;
            this.next = next;
        }
    }
}

然后關注字段的原子更新。

AtomicIntegerFieldUpdater<T>/AtomicLongFieldUpdater<T>/AtomicReferenceFieldUpdater<T,V>是基于反射的原子更新字段的值。

相應的API也是非常簡單的,但是也是有一些約束的。

(1)字段必須是volatile類型的!volatile到底是個什么東西。請查看Java中Volatile關鍵字詳解

(2)字段的描述類型(修飾符public/protected/default/private)是與調用者與操作對象字段的關系一致。也就是說調用者能夠直接操作對象字段,那么就可以反射進行原子操作。但是對于父類的字段,子類是不能直接操作的,盡管子類可以訪問父類的字段。

(3)只能是實例變量,不能是類變量,也就是說不能加static關鍵字。

(4)只能是可修改變量,不能使final變量,因為final的語義就是不可修改。實際上final的語義和volatile是有沖突的,這兩個關鍵字不能同時存在。

(5)對于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long類型的字段,不能修改其包裝類型(Integer/Long)。如果要修改包裝類型就需要使用AtomicReferenceFieldUpdater。

在下面的例子中描述了操作的方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicIntegerFieldUpdaterDemo {
    class DemoData{
        public volatile int value1 = 1;
        volatile int value2 = 2;
        protected volatile int value3 = 3;
        private volatile int value4 = 4;
    }
    AtomicIntegerFieldUpdater<DemoData> getUpdater(String fieldName) {
        return AtomicIntegerFieldUpdater.newUpdater(DemoData.class, fieldName);
    }
    void doit() {
        DemoData data = new DemoData();
        System.out.println("1 ==> "+getUpdater("value1").getAndSet(data, 10));
        System.out.println("3 ==> "+getUpdater("value2").incrementAndGet(data));
        System.out.println("2 ==> "+getUpdater("value3").decrementAndGet(data));
        System.out.println("true ==> "+getUpdater("value4").compareAndSet(data, 4, 5));
    }
    public static void main(String[] args) {
        AtomicIntegerFieldUpdaterDemo demo = new AtomicIntegerFieldUpdaterDemo();
        demo.doit();
    }
}

在上面的例子中DemoData的字段value3/value4對于AtomicIntegerFieldUpdaterDemo類是不可見的,因此通過反射是不能直接修改其值的。

AtomicMarkableReference類描述的一個<Object,Boolean>的對,可以原子的修改Object或者Boolean的值,這種數據結構在一些緩存或者狀態描述中比較有用。這種結構在單個或者同時修改Object/Boolean的時候能夠有效的提高吞吐量。

AtomicStampedReference類維護帶有整數“標志”的對象引用,可以用原子方式對其進行更新。對比AtomicMarkableReference類的<Object,Boolean>,AtomicStampedReference維護的是一種類似<Object,int>的數據結構,其實就是對對象(引用)的一個并發計數。但是與AtomicInteger不同的是,此數據結構可以攜帶一個對象引用(Object),并且能夠對此對象和計數同時進行原子操作。

在本文結尾會提到“ABA問題”,而AtomicMarkableReference/AtomicStampedReference在解決“ABA問題”上很有用。

三、Atomic類的作用

使得讓對單一數據的操作,實現了原子化

使用Atomic類構建復雜的,無需阻塞的代碼

訪問對2個或2個以上的atomic變量(或者對單個atomic變量進行2次或2次以上的操作)通常認為是需要同步的,以達到讓這些操作能被作為一個原子單元。

無鎖定且無等待算法

基于CAS(compareandswap)的并發算法稱為無鎖定算法,因為線程不必再等待鎖定(有時稱為互斥或關鍵部分,這取決于線程平臺的術語)。無論CAS操作成功還是失敗,在任何一種情況中,它都在可預知的時間內完成。如果CAS失敗,調用者可以重試CAS操作或采取其他適合的操作。

如果每個線程在其他線程任意延遲(或甚至失敗)時都將持續進行操作,就可以說該算法是無等待的。與此形成對比的是,無鎖定算法要求僅某個線程總是執行操作。(無等待的另一種定義是保證每個線程在其有限的步驟中正確計算自己的操作,而不管其他線程的操作、計時、交叉或速度。這一限制可以是系統中線程數的函數;例如,如果有10個線程,每個線程都執行一次CasCounter.increment()操作,最壞的情況下,每個線程將必須重試最多九次,才能完成增加。)

再過去的15年里,人們已經對無等待且無鎖定算法(也稱為無阻塞算法)進行了大量研究,許多人通用數據結構已經發現了無阻塞算法。無阻塞算法被廣泛用于操作系統和JVM級別,進行諸如線程和進程調度等任務。雖然它們的實現比較復雜,但相對于基于鎖定的備選算法,它們有許多優點:可以避免優先級倒置和死鎖等危險,競爭比較便宜,協調發生在更細的粒度級別,允許更高程度的并行機制等等。

常見的:

非阻塞的計數器Counter

非阻塞堆棧ConcurrentStack

非阻塞的鏈表ConcurrentLinkedQueue

ABA問題:

因為在更改V之前,CAS主要詢問“V的值是否仍為A”,所以在第一次讀取V以及對V執行CAS操作之前,如果將值從A改為B,然后再改回A,會使基于CAS的算法混亂。在這種情況下,CAS操作會成功,但是在一些情況下,結果可能不是您所預期的。這類問題稱為ABA問題,通常通過將標記或版本編號與要進行CAS操作的每個值相關聯,并原子地更新值和標記,來處理這類問題。AtomicStampedReference類支持這種方法。

總結

以上就是本文關于Java多線程Atomic包操作原子變量與原子類詳解的全部內容,希望對大家有所幫助。如有不足之處,歡迎留言指出。

原文鏈接:http://blog.csdn.net/vernonzheng/article/details/8206349

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 狠狠色婷婷丁香六月 | 垫底辣妹免费观看完整版 | 亚洲人成伊人成综合网久久 | 国产人成激情视频在线观看 | 国产成人久久久精品一区二区三区 | 盲井在线 | 91禁漫 | 日日日操 | 1769国产精品免费视频 | 国产第一福利影院 | 国产日韩欧美综合一区二区三区 | 婷婷久久精品 | 色人阁导航 | beeg最新| 成人免费国产欧美日韩你懂的 | 2014天堂| 国产三区二区 | 青草久久精品亚洲综合专区 | 免费特黄一级欧美大片 | 青草网址 | 免费欧美一级片 | 星空无限传媒xk8129 | 日本天堂影院在线播放 | xxxxyoujizz护士 | 女教师三级做受 | caoporn超碰| 护士的小嫩嫩好紧好舒服 | 亚洲六月丁香六月婷婷蜜芽 | 天堂8在线天堂资源bt | 亚洲天堂在线视频观看 | 女人与zzzooooxxx | 美女被狂揉下部羞羞动漫 | 免费观看在线永久免费xx视频 | 亚洲高清中文字幕一区二区三区 | 五月婷婷在线观看 | 国产品精人成福利视频 | 99只有精品 | 色综合视频一区二区三区 | 四虎成人4hutv影院 | 亚洲zooz人禽交xxxx | 逼里逼里香 |