日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java中的Atomic包

發(fā)布時(shí)間:2025/3/18 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中的Atomic包 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Atomic包的作用

方便程序員在多線程環(huán)境下,無鎖的進(jìn)行原子操作

Atomic包核心

Atomic包里的類基本都是使用Unsafe實(shí)現(xiàn)的包裝類,核心操作是CAS原子操作;

關(guān)于CAS

compare and swap,比較和替換技術(shù),將預(yù)期值與當(dāng)前變量的值比較(compare),如果相等則使用新值替換(swap)當(dāng)前變量,否則不作操作;

現(xiàn)代CPU已廣泛支持CAS指令,如果不支持,那么JVM將使用自旋鎖,與互斥鎖一樣,兩者都需先獲取鎖才能訪問共享資源,但互斥鎖會(huì)導(dǎo)致線程進(jìn)入睡眠,而自旋鎖會(huì)一直循環(huán)等待直到獲取鎖;

另外,有一點(diǎn)需要注意的是CAS操作中的ABA問題,即將預(yù)期值與當(dāng)前變量的值比較的時(shí)候,即使相等也不能保證變量沒有被修改過,因?yàn)樽兞靠赡苡葾變成B再變回A,解決該問題,可以給變量增加一個(gè)版本號(hào),每次修改變量時(shí)版本號(hào)自增,比較的時(shí)候,同時(shí)比較變量的值和版本號(hào)即可;

Atomic包主要提供四種原子更新方式

  • 原子方式更新基本類型;
  • 原子方式更新數(shù)組;
  • 原子方式更新引用;
  • 原子方式更新字段;

原子方式更新基本類型

以下三個(gè)類是以原子方式更新基本類型

  • AtomicBoolean:原子更新布爾類型。
  • AtomicInteger:原子更新整型。
  • AtomicLong:原子更新長(zhǎng)整型。

以AtomicInteger為例,

package concurrency; import java.util.concurrent.atomic.AtomicInteger;public class AtomicIntegerTest {static AtomicInteger ai = new AtomicInteger(1);public static void main(String[] args) {//相當(dāng)于i++,返回的是舊值,看方法名就知道,先獲取再自增 System.out.println(ai.getAndIncrement());System.out.println(ai.get());//先自增,再獲取 System.out.println(ai.incrementAndGet());System.out.println(ai.get());//增加一個(gè)指定值,先add,再getSystem.out.println(ai.addAndGet(5));System.out.println(ai.get());//增加一個(gè)指定值,先get,再setSystem.out.println(ai.getAndSet(5));System.out.println(ai.get());}}

注意:Atomic包提供了三種基本類型的原子更新,剩余的Java的基本類型還有char,float和double等,其更新方式可以參考AtomicBoolean的思路來現(xiàn),AtomicBoolean是把boolean轉(zhuǎn)成整型再調(diào)用compareAndSwapInt進(jìn)行CAS來實(shí)現(xiàn)的,類似的short和byte也可以轉(zhuǎn)成整形,float和double可以利用Float.floatToIntBits,Double.doubleToLongBits轉(zhuǎn)成整形和長(zhǎng)整形進(jìn)行相應(yīng)處理;

原子方式更新數(shù)組

以下三個(gè)類是以原子方式更新數(shù)組,

  • AtomicIntegerArray:原子更新整型數(shù)組里的元素。
  • AtomicLongArray:原子更新長(zhǎng)整型數(shù)組里的元素。
  • AtomicReferenceArray:原子更新引用類型數(shù)組里的元素。

以AtomicIntegerArray為例,其方法與AtomicInteger很像,多了個(gè)數(shù)組下標(biāo)索引;

package concurrency;import java.util.concurrent.atomic.AtomicIntegerArray;public class AtomicIntegerArrayTest {static int[] valueArr = new int[] { 1, 2 };//AtomicIntegerArray內(nèi)部會(huì)拷貝一份數(shù)組static AtomicIntegerArray ai = new AtomicIntegerArray(valueArr);public static void main(String[] args) {ai.getAndSet(0, 3);//不會(huì)修改原始數(shù)組valueSystem.out.println(ai.get(0));System.out.println(valueArr[0]);}}

原子方式更新引用

以下三個(gè)類是以原子方式更新引用,與其它不同的是,更新引用可以更新多個(gè)變量,而不是一個(gè)變量;

  • AtomicReference:原子更新引用類型。
  • AtomicReferenceFieldUpdater:原子更新引用類型里的字段。
  • AtomicMarkableReference:原子更新帶有標(biāo)記位的引用類型。

以AtomicReference為例,

package concurrency;import java.util.concurrent.atomic.AtomicReference;public class AtomicReferenceTest {public static AtomicReference<User> atomicUserRef = new AtomicReference<User>();public static void main(String[] args) {User user = new User("conan", 15);atomicUserRef.set(user);User updateUser = new User("Shinichi", 17);atomicUserRef.compareAndSet(user, updateUser);System.out.println(atomicUserRef.get().getName());System.out.println(atomicUserRef.get().getOld());}static class User {private String name;private int old;public User(String name, int old) {this.name = name;this.old = old;}public String getName() {return name;}public int getOld() {return old;}} }

原子方式更新字段

以下三個(gè)類是以原子方式更新字段,

  • AtomicIntegerFieldUpdater:原子更新整型字段的更新器。
  • AtomicLongFieldUpdater:原子更新長(zhǎng)整型字段的更新器。
  • AtomicStampedReference:原子更新帶有版本號(hào)的引用類型,用于解決使用CAS進(jìn)行原子更新時(shí),可能出現(xiàn)的ABA問題。

以AtomicIntegerFieldUpdater為例,

package concurrency;import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;public class AtomicIntegerFieldUpdaterTest {private static AtomicIntegerFieldUpdater<User> a = AtomicIntegerFieldUpdater.newUpdater(User.class, "old");public static void main(String[] args) {User conan = new User("conan", 10);System.out.println(a.getAndIncrement(conan));System.out.println(a.get(conan));}public static class User {private String name;//注意需要用volatile修飾public volatile int old;public User(String name, int old) {this.name = name;this.old = old;}public String getName() {return name;}public int getOld() {return old;}} }

參考資料

http://ifeve.com/java-atomic/

《JAVA并發(fā)編程實(shí)戰(zhàn)》

轉(zhuǎn)載于:https://www.cnblogs.com/chenpi/p/5375805.html

與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的Java中的Atomic包的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。