偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

聊一聊Java中的原子類

開發(fā) 后端
本節(jié)介紹Java中的原子類是java.util.concurrent.atomic包下的對象,他們之所以有原子性的共性,都來源于CAS,可見CAS的重要性。對于原子類變量的操作是不會存在并發(fā)性問題的,不需要使用同步手段進行并發(fā)控制。

在前面的內(nèi)容中,我們已經(jīng)學習了CAS的原理,所以對于學習本節(jié)來說會非常容易。本節(jié)介紹Java中的原子類是java.util.concurrent.atomic包下的對象,他們之所以有原子性的共性,都來源于CAS,可見CAS的重要性。對于原子類變量的操作是不會存在并發(fā)性問題的,不需要使用同步手段進行并發(fā)控制。它底層自身的實現(xiàn)即可保證變量的可見性以及操作的原子性,一般我們可以使用AtomicInteger,AtomicLong等實現(xiàn)計數(shù)器等功能,利用AtomicBoolean實現(xiàn)標志位等功能。

原子類是JDK5提供的,當時只有12個原子類,發(fā)展到JDK8時,又多出了4個原子類,如下圖2-25所示,紅色框內(nèi)為JDK8新增加的。

 

圖2-25 Java16個原子類

下面我們來對這些原子類進行分類講解。

2.10.1原子更新基本類型

l AtomicBoolean: 原子更新布爾類型。

l AtomicInteger: 原子更新整型。

l AtomicLong: 原子更新長整型。

我們以AtomicInteger為例,AtomicIngeter的常用方法如下:

n int addAndGet(int delta): 以原子的方式將參數(shù)與實例中的值相加,并返回結(jié)果。

n boolean compareAndSet(int expect, int update): 如果輸入的值等于預(yù)期值,則以原子方式將該值設(shè)置為輸入的值。

n int getAndIncrement(): 以原子的方式將當前值加1,然后返回自增前的值,也就是舊值。此方法也是比較常用的方法,可以用來做計數(shù)器。

n void lazySet(int newValue): 最終會設(shè)置成newValue,使用lazySet設(shè)置值后,可能導致其他線程在之后的一小段時間內(nèi)還是可以讀到舊的值。

n int getAndSet(int newValue): 以原子的方式設(shè)置為newValue,并返回舊值。

n int incrementAndGet(): 和getAndIncrement一樣,他返回的是自增后的值。

記得在講解CAS應(yīng)用的代碼案例中,使用過原子自增的方法,下面我們看看getAndIncrement() 是如何實現(xiàn)原子操作的,請看2-45示例代碼中AtomicInteger部分源碼。

代碼清單2-45 AtomicInteger.java

  1. public final int getAndIncrement() { 
  2.         return unsafe.getAndAddInt(this, valueOffset, 1); 
  3.     } 
  4.  
  5. public final int getAndAddInt(Object var1, long var2, int var4) { 
  6.         int var5; 
  7.         do { 
  8.             var5 = this.getIntVolatile(var1, var2); 
  9.         } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); 
  10.  
  11.         return var5; 
  12.     } 

我們?nèi)〉昧伺f值,然后把要加的數(shù)傳過去,調(diào)用getAndAddInt () 進行原子更新操作,實際最核心的方法是 compareAndSwapInt(),使用CAS進行更新。我們Unsafe只提供了3中CAS操作,另外注意,AtomicBoolean 是把Boolean轉(zhuǎn)成整型,在使用 compareAndSwapInt 進行操作的。在atomic包里的對象基本都是使用Unsafe提供的3中CAS操作的方法實現(xiàn)的,請看Unsafe源碼,如代碼清單2-46所示。

代碼清單2-46 Unsafe.java

  1. /** 
  2.  * 如果當前數(shù)值是var4,則原子的將java變量更新成var5或var6 
  3.  * @return 如果更新成功返回true 
  4.  */ 
  5. public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5); 
  6.  
  7.     public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5); 
  8.  
  9.     public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6); 

2.10.2原子更新數(shù)組

l AtomicIntegerArray: 原子更新整型數(shù)組里的元素。

l AtomicLongArray: 原子更新長整型數(shù)組里的元素。

l AtomicReferenceArray: 原子更新引用類型數(shù)組里的元素。

這三個類的最常用的方法是如下兩個方法:

n get(int index):獲取索引為index的元素值。

n compareAndSet(int i, int expect, int update): 如果當前值等于預(yù)期值,則以原子方式將數(shù)組位置 i 的元素設(shè)置為update值。

2.10.3原子更新引用類型

l AtomicReference: 原子更新引用類型。

l AtomicReferenceFieldUpdater: 原子更新引用類型的字段。

l AtomicMarkableReferce: 原子更新帶有標記位的引用類型,可以使用構(gòu)造方法更新一個布爾類型的標記位和引用類型。

這三個類提供的方法都差不多,首先構(gòu)造一個引用對象,然后把引用對象set進Atomic類,然后調(diào)用compareAndSet等一些方法去進行原子操作,原理都是基于Unsafe實現(xiàn),但AtomicReferenceFieldUpdater略有不同,更新的字段必須用volatile修飾。下面我們使用原子引用類型寫一個簡單的Demo,請看示例代碼2-47所示

代碼清單2-47 AtomicReferenceDemo.java

  1. public class AtomicReferenceDemo { 
  2.     public static AtomicReference<User> ai = new AtomicReference<User>(); 
  3.  
  4.     public static void main(String[] args) { 
  5.  
  6.         User u1 = new User("pangHu", 18); 
  7.         ai.set(u1); 
  8.         User u2 = new User("pangPang", 15); 
  9.         ai.compareAndSet(u1, u2); 
  10.         System.out.println(ai.get().getAge() + ai.get().getName()); 
  11.     } 
  12.  
  13.     static class User { 
  14.         private String name
  15.         private int age; 
  16.  //省略getter、settrt 
  17.     } 

輸出結(jié)果。

15pangPang

2.10.4原子更新字段類

如果需要原子的更新類里某個字段時,需要用到原子更新字段類,Atomic包提供了3個類進行原子字段更新:

l AtomicIntegerFieldUpdater: 原子更新整型的字段的更新器。

l AtomicLongFieldUpdater: 原子更新長整型字段的更新器。

l AtomicStampedFieldUpdater: 原子更新帶有版本號的引用類型。該方法比較重要,他和引用類型加上一個整數(shù)值,可以控制數(shù)據(jù)的版本號,這樣就可以解決CAS更新時可能出現(xiàn)的ABA問題。和引用類型一樣更新類的字段必須使用 public volatile 修飾。

2.10.5 JDK8新增原子類簡介

l DoubleAccumulator

l LongAccumulator

l DoubleAdder

l LongAdder

下面以 LongAdder 為例介紹一下,并列出使用注意事項。

這些類對應(yīng)把 AtomicLong 等類的改進。比如 LongAccumulator 與 LongAdder 在高并發(fā)環(huán)境下比 AtomicLong 更高效。

Atomic、Adder在低并發(fā)環(huán)境下,兩者性能很相似。但在高并發(fā)環(huán)境下,Adder 有著明顯更高的吞吐量,但是有著更高的空間復雜度。

LongAdder其實是LongAccumulator的一個特例,調(diào)用LongAdder相當使用下面的方式調(diào)用LongAccumulator。

sum()方法在沒有并發(fā)的情況下調(diào)用,如果在并發(fā)情況下使用會存在計數(shù)不準,下面有代碼為例。

LongAdder不可以代替AtomicLong,雖然 LongAdder的add()方法可以原子性操作,但是并沒有使用 Unsafe 的CAS算法,只是使用了CAS的思想。

 

LongAdder其實是LongAccumulator的一個特例,調(diào)用LongAdder相當使用下面的方式調(diào)用LongAccumulator,LongAccumulator提供了比LongAdder更強大的功能,構(gòu)造函數(shù)其中accumulatorFunction一個雙目運算器接口,根據(jù)輸入的兩個參數(shù)返回一個計算值,identity則是LongAccumulator累加器的初始值。

本文轉(zhuǎn)載自微信公眾號「晏霖」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系晏霖公眾號。

 

責任編輯:武曉燕 來源: 晏霖
相關(guān)推薦

2019-12-02 16:23:03

Python編程語言“垃圾”回收

2022-08-30 07:39:57

C++namespace隔離

2022-08-08 08:25:21

Javajar 文件

2021-01-04 08:09:07

Linux內(nèi)核Watchdog

2021-06-30 07:19:35

微服務(wù)業(yè)務(wù)MySQL

2020-09-08 06:54:29

Java Gradle語言

2019-12-12 14:52:10

數(shù)據(jù)庫腳本

2022-11-09 08:05:15

JavaScriptsuper()

2024-10-16 15:11:58

消息隊列系統(tǒng)設(shè)計

2022-03-06 20:35:41

并發(fā)串行CAP

2023-07-06 13:56:14

微軟Skype

2018-06-07 13:17:12

契約測試單元測試API測試

2023-09-22 17:36:37

2021-01-28 22:31:33

分組密碼算法

2020-05-22 08:16:07

PONGPONXG-PON

2021-12-06 09:43:01

鏈表節(jié)點函數(shù)

2021-07-16 11:48:26

模型 .NET微軟

2023-09-20 23:01:03

Twitter算法

2021-03-01 18:37:15

MySQL存儲數(shù)據(jù)

2018-07-23 15:28:29

HTTPCookieHeader
點贊
收藏

51CTO技術(shù)棧公眾號