最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java原子操作CAS原理解析

 更新時間:2019年10月25日 10:08:46   作者:ねぇ  
這篇文章主要介紹了Java原子操作CAS原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

一、CAS(Compare And Set)

Compare And Set(或Compare And Swap),CAS是解決多線程并行情況下使用鎖造成性能損耗的一種機制,CAS操作包含三個操作數(shù)——內存位置(V)、預期原值(A)、新值(B)。如果內存位置的值與預期原值相匹配,那么處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。無論哪種情況,它都會在CAS指令之前返回該位置的值。CAS有效地說明了“我認為位置V應該包含值A;如果包含該值,則將B放到這個位置;否則,不要更改該位置,只告訴我這個位置現(xiàn)在的值即可。

​ 在java中可以通過鎖和循環(huán)CAS的方式來實現(xiàn)原子操作。Java中 java.util.concurrent.atomic包相關類就是 CAS的實現(xiàn),atomic包里包括以下類:

AtomicBoolean 可以用原子方式更新的 boolean 值。
AtomicInteger 可以用原子方式更新的 int 值。
AtomicIntegerArray 可以用原子方式更新其元素的 int 數(shù)組。
AtomicIntegerFieldUpdater 基于反射的實用工具,可以對指定類的指定 volatile int 字段進行原子更新。
AtomicLong 可以用原子方式更新的 long 值。
AtomicLongArray 可以用原子方式更新其元素的 long 數(shù)組。
AtomicLongFieldUpdater 基于反射的實用工具,可以對指定類的指定 volatile long 字段進行原子更新。
AtomicMarkableReference AtomicMarkableReference 維護帶有標記位的對象引用,可以原子方式對其進行更新。
AtomicReference 可以用原子方式更新的對象引用。
AtomicReferenceArray 可以用原子方式更新其元素的對象引用數(shù)組。
AtomicReferenceFieldUpdater<T,V> 基于反射的實用工具,可以對指定類的指定 volatile 字段進行原子更新。
AtomicStampedReference AtomicStampedReference 維護帶有整數(shù)“標志”的對象引用,可以用原子方式對其進行更新。

二、AtomicInteger

AtomicInteger可以用原子方式更新的 int 值。AtomicInteger 可用在應用程序中(如以原子方式增加的計數(shù)器),并且不能用于替換 Integer。但是,此類確實擴展了 Number,允許那些處理基于數(shù)字類的工具和實用工具進行統(tǒng)一訪問。 我們拿 AtomicInteger為例來學習下 CAS操作是如何實現(xiàn)的。

通常情況下,在 Java中,i++等類似操作并不是線程安全的,因為 i++可分為三個獨立的操作:獲取變量當前值,為該值+1,然后寫回新的值。在沒有額外資源可以利用的情況下,只能使用加鎖才能保證讀-改-寫這三個操作時“原子性”的。但是利用加鎖的方式來實現(xiàn)該功能的話,代碼將非常復雜及難以維護,如:

synchronized (lock) { 
  i++; 
} 

相關類中還需要增加 Object lock等額外標志,這樣就帶來了很多麻煩,增加了很多業(yè)務無關代碼,給開發(fā)與維護帶來了不便。
​ 然而利用 atomic包中相關類型就可以很簡單實現(xiàn)此操作,以下是一個計數(shù)程序實例:

public class Counter {
  private AtomicInteger ai = new AtomicInteger();
  private int i = 0;
 
  public static void main(String[] args) { 
    final Counter cas = new Counter(); 
    List<Thread> threads = new ArrayList<Thread>();
    // 添加100個線程 
    for (int j = 0; j < 100; j++) { 
      threads.add(new Thread(new Runnable() {
        public void run() { 
          // 執(zhí)行100次計算,預期結果應該是10000 
          for (int i = 0; i < 100; i++) { 
            cas.count(); 
            cas.safeCount(); 
          } 
        } 
      })); 
    } 
    //開始執(zhí)行 
    for (Thread t : threads) {
      t.start(); 
    } 
    // 等待所有線程執(zhí)行完成 
    for (Thread t : threads) {
      try { 
        t.join(); 
      } catch (InterruptedException e) { 
        e.printStackTrace(); 
      } 
    } 
    System.out.println("非線程安全計數(shù)結果:"+cas.i); 
    System.out.println("線程安全計數(shù)結果:"+cas.ai.get()); 
  } 
 
  /** 使用CAS實現(xiàn)線程安全計數(shù)器 */ 
  private void safeCount() { 
    for (;;) { 
      int i = ai.get(); 
      // 如果當前值 == 預期值,則以原子方式將該值設置為給定的更新值 
      boolean suc = ai.compareAndSet(i, ++i); 
      if (suc) { 
        break; 
      } 
    } 
  } 
  /** 非線程安全計數(shù)器 */ 
  private void count() { 
    i++; 
  } 
} 
/**
非線程安全計數(shù)結果:9942
線程安全計數(shù)結果:10000
*/

其中非線程安全計數(shù)器所計算的結果每次都不相同且不正確,而線程安全計數(shù)器計算的結果每次都是正確的。

三、存在的問題

CAS雖然很高效的解決原子操作,但是CAS仍然存在三大問題:ABA問題、循環(huán)時間長開銷大、只能保證一個共享變量的原子操作。

ABA問題:因為CAS需要在操作值的時候檢查下值有沒有發(fā)生變化,如果沒有發(fā)生變化則更新,但是如果一個值原來是A,變成了B,又變成了A,那么使用CAS進行檢查時會發(fā)現(xiàn)它的值沒有發(fā)生變化,但是實際上卻變化了。ABA問題的解決思路就是使用版本號。在變量前面追加上版本號,每次變量更新的時候把版本號加一,那么A-B-A 就會變成1A-2B-3A。 從Java1.5開始JDK的 atomic包里提供了一個類AtomicStampedReference 來解決ABA問題。這個類的 compareAndSet方法作用是首先檢查當前引用是否等于預期引用,并且當前標志是否等于預期標志,如果全部相等,則以原子方式將該引用和該標志的值設置為給定的更新值。

循環(huán)時間長開銷大:自旋CAS如果長時間不成功,會給CPU帶來非常大的執(zhí)行開銷。如果JVM能支持處理器提供的pause指令那么效率會有一定的提升,pause指令有兩個作用,第一它可以延遲流水線執(zhí)行指令(de-pipeline),使CPU不會消耗過多的執(zhí)行資源,延遲的時間取決于具體實現(xiàn)的版本,在一些處理器上延遲時間是零。第二它可以避免在退出循環(huán)的時候因內存順序沖突(memory order violation)而引起CPU流水線被清空(CPU pipeline flush),從而提高CPU的執(zhí)行效率?!?/p>

只能保證一個共享變量的原子操作:當對一個共享變量執(zhí)行操作時,我們可以使用循環(huán)CAS的方式來保證原子操作,但是對多個共享變量操作時,循環(huán)CAS就無法保證操作的原子性,這個時候就可以用鎖,或者有一個取巧的辦法,就是把多個共享變量合并成一個共享變量來操作。比如有兩個共享變量i=2,j=a,合并一下ij=2a,然后用CAS來操作ij。從Java1.5開始JDK提供了AtomicReference類來保證引用對象之間的原子性,你可以把多個變量放在一個對象里來進行CAS操作。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:

相關文章

  • Maven項目如何查找jar包是由哪個依賴引入的

    Maven項目如何查找jar包是由哪個依賴引入的

    這篇文章主要介紹了Maven項目如何查找jar包是由哪個依賴引入的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java?Stream流語法示例詳解

    Java?Stream流語法示例詳解

    這篇文章主要為大家詳細介紹了Java的Stream流,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • Java中equals方法使用及重寫練習

    Java中equals方法使用及重寫練習

    equals是在object類中的方法,在object中equals是用來看看兩個參數(shù)是否引用的是同一個對象,下面這篇文章主要給大家介紹了關于Java中equals方法使用及重寫練習的相關資料,需要的朋友可以參考下
    2023-05-05
  • 使用@Builder導致無法創(chuàng)建無參構造方法的解決

    使用@Builder導致無法創(chuàng)建無參構造方法的解決

    這篇文章主要介紹了使用@Builder導致無法創(chuàng)建無參構造方法的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 解決SpringMVC 返回Java8 時間JSON數(shù)據(jù)的格式化問題處理

    解決SpringMVC 返回Java8 時間JSON數(shù)據(jù)的格式化問題處理

    本篇文章主要介紹了解決SpringMVC 返回Java8 時間JSON數(shù)據(jù)的格式化問題處理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • Java實現(xiàn)讀取和寫入properties文件

    Java實現(xiàn)讀取和寫入properties文件

    這篇文章主要介紹了Java實現(xiàn)讀取和寫入properties文件方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 解決SpringBoot啟動報錯:Failed?to?load?property?source?from?location?'classpath:/application.yml'問題

    解決SpringBoot啟動報錯:Failed?to?load?property?source?from?l

    這篇文章主要介紹了解決SpringBoot啟動報錯:Failed?to?load?property?source?from?location?'classpath:/application.yml'問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 使用FeignClient設置動態(tài)Url

    使用FeignClient設置動態(tài)Url

    這篇文章主要介紹了使用FeignClient設置動態(tài)Url方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • SpringBoot整合Thymeleaf的方法

    SpringBoot整合Thymeleaf的方法

    這篇文章主要介紹了SpringBoot整合Thymeleaf的方法,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • java實現(xiàn)json字符串格式化處理的工具類

    java實現(xiàn)json字符串格式化處理的工具類

    這篇文章主要為大家詳細介紹了如何使用java實現(xiàn)json字符串格式化處理的工具類,文中的示例代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-01-01

最新評論

六枝特区| 江孜县| 钟山县| 恩施市| 萨迦县| 鹤壁市| 桐乡市| 喜德县| 伊宁县| 抚松县| 蕲春县| 奎屯市| 芜湖市| 虎林市| 静宁县| 海城市| 饶阳县| 乌兰县| 拉萨市| 和平区| 临夏县| 上栗县| 天门市| 法库县| 资中县| 中方县| 西城区| 沙雅县| 大厂| 仙游县| 宜丰县| 清流县| 铜鼓县| 全椒县| 太仓市| 阜城县| 常宁市| 和龙市| 吉木萨尔县| 秦安县| 铁岭县|