成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

什么是ABA問題?Java里面的原生解決方案是什么?原理是什么?

開發 后端
AtomicStampedReference是一個帶有時間戳的對象引用,能很好的解決CAS機制中的ABA問題,這篇文章將通過案例對其介紹分析。

[[380084]]

 AtomicStampedReference是一個帶有時間戳的對象引用,能很好的解決CAS機制中的ABA問題,這篇文章將通過案例對其介紹分析。

一、ABA問題

ABA問題是CAS機制中出現的一個問題,他的描述是這樣的。我們直接畫一張圖來演示,

什么意思呢?就是說一個線程把數據A變為了B,然后又重新變成了A。此時另外一個線程讀取的時候,發現A沒有變化,就誤以為是原來的那個A。這就是有名的ABA問題。ABA問題會帶來什么后果呢?我們舉個例子。

一個小偷,把別人家的錢偷了之后又還了回來,還是原來的錢嗎,ABA問題也一樣,如果不好好解決就會帶來大量的問題。最常見的就是資金問題,也就是別人如果挪用了你的錢,在你發現之前又還了回來。但是別人卻已經觸犯了法律。

如何去解決這個ABA問題呢,就是使用今天所說的AtomicStampedReference。

二、AtomicStampedReference

1、問題解決

我們先給出一個ABA的例子,對ABA問題進行場景重現。

  1. public class AtomicTest { 
  2.  private static AtomicInteger index = new AtomicInteger(10); 
  3.  public static void main(String[] args) { 
  4.   new Thread(() -> { 
  5.    index.compareAndSet(10, 11); 
  6.    index.compareAndSet(11, 10); 
  7.    System.out.println(Thread.currentThread().getName()+ 
  8.      ":10->11->10"); 
  9.   },"張三").start(); 
  10.    
  11.   new Thread(() -> { 
  12.    try { 
  13.     TimeUnit.SECONDS.sleep(2); 
  14.     boolean isSuccess = index.compareAndSet(10, 12); 
  15.     System.out.println(Thread.currentThread().getName()+ 
  16.       ":index是預期的10嘛,"+isSuccess 
  17.       +"   設置的新值是:"+index.get()); 
  18.    } catch (InterruptedException e) { 
  19.     e.printStackTrace(); 
  20.    } 
  21.   },"李四").start(); 
  22.  } 

在上面的代碼中,我們使用張三線程,對index10->11->10的變化,然后李四線程讀取index觀察是否有變化,并設置新值。運行一下看看結果:

這個案例重現了ABA的問題場景,下面我們看如何使用AtomicStampedReference解決這個問題的。

  1. public class AtomicTest2 { 
  2.  private static AtomicInteger index = new AtomicInteger(10); 
  3.  static AtomicStampedReference<Integer> stampRef  
  4.        = new AtomicStampedReference(10, 1); 
  5.  public static void main(String[] args) { 
  6.   new Thread(() -> { 
  7.    int stamp = stampRef.getStamp(); 
  8.    System.out.println(Thread.currentThread().getName()  
  9.      + " 第1次版本號: " + stamp); 
  10.    stampRef.compareAndSet(10, 11,stampRef.getStamp(),stampRef.getStamp()+1); 
  11.    System.out.println(Thread.currentThread().getName()  
  12.      + " 第2次版本號: " + stampRef.getStamp()); 
  13.    stampRef.compareAndSet(11, 10,stampRef.getStamp(),stampRef.getStamp()+1); 
  14.    System.out.println(Thread.currentThread().getName()  
  15.      + " 第3次版本號: " + stampRef.getStamp()); 
  16.   },"張三").start(); 
  17.    
  18.   new Thread(() -> { 
  19.    try { 
  20.     int stamp = stampRef.getStamp(); 
  21.     System.out.println(Thread.currentThread().getName()  
  22.       + " 第1次版本號: " + stamp); 
  23.     TimeUnit.SECONDS.sleep(2); 
  24.     boolean isSuccess =stampRef.compareAndSet(10, 12, 
  25.       stampRef.getStamp(),stampRef.getStamp()+1); 
  26.     System.out.println(Thread.currentThread().getName()  
  27.       + " 修改是否成功: "+ isSuccess+" 當前版本 :" + stampRef.getStamp()); 
  28.     System.out.println(Thread.currentThread().getName()  
  29.       + " 當前實際值: " + stampRef.getReference()); 
  30.    } catch (InterruptedException e) { 
  31.     e.printStackTrace(); 
  32.    } 
  33.   },"李四").start(); 
  34.  } 

上面的代碼我們再來分析一下,我們會發現AtomicStampedReference里面增加了一個時間戳,也就是說每一次修改只需要設置不同的版本好即可。我們先運行一邊看看:

這里使用的是AtomicStampedReference的compareAndSet函數,這里面有四個參數:

compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp)。

(1)第一個參數expectedReference:表示預期值。

(2)第二個參數newReference:表示要更新的值。

(3)第三個參數expectedStamp:表示預期的時間戳。

(4)第四個參數newStamp:表示要更新的時間戳。

這個compareAndSet方法到底是如何實現的,我們深入到源碼中看看。

2、源碼分析

  1. public boolean compareAndSet(V   expectedReference, 
  2.                                 V   newReference, 
  3.                                 int expectedStamp, 
  4.                                 int newStamp) { 
  5.        Pair<V> current = pair; 
  6.        return 
  7.            expectedReference == current.reference && 
  8.            expectedStamp == current.stamp && 
  9.            ((newReference == current.reference && 
  10.              newStamp == current.stamp) || 
  11.             casPair(current, Pair.of(newReference, newStamp))); 
  12.    } 

剛剛這四個參數的意思已經說了,我們主要關注的就是實現,首先我們看到的就是這個Pair,因此想要弄清楚,我們再看看這個Pair是什么,

  1. private static class Pair<T> { 
  2.      final T reference; 
  3.      final int stamp; 
  4.      private Pair(T reference, int stamp) { 
  5.          this.reference = reference; 
  6.          this.stamp = stamp; 
  7.      } 
  8.      static <T> Pair<T> of(T reference, int stamp) { 
  9.          return new Pair<T>(reference, stamp); 
  10.      } 
  11.  } 

在這里我們會發現Pair里面只是包存了值reference和時間戳stamp。

在compareAndSet方法中最后還調用了casPair方法,從名字就可以看到,主要是使用CAS機制更新新的值reference和時間戳stamp。我們可以進入這個方法中看看。

  1. //底層調用的是UNSAFE的compareAndSwapObject方法 
  2.  
  3.  private boolean casPair(Pair<V> cmp, Pair<V> val) { 
  4.      return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); 
  5.  } 

三、總結

其實除了AtomicStampedReference類,還有一個原子類也可以解決,就是AtomicMarkableReference,它不是維護一個版本號,而是維護一個boolean類型的標記,用法沒有AtomicStampedReference靈活。因此也只是在特定的場景下使用。

本文轉載自微信公眾號「愚公要移山」,可以通過以下二維碼關注。轉載本文請聯系愚公要移山公眾號。

 

責任編輯:武曉燕 來源: 愚公要移山
相關推薦

2021-02-08 21:07:47

JavaCAS機制

2024-11-19 17:54:15

JavaCASABA問題

2021-02-02 09:37:20

CQRS系統數據庫

2024-11-25 12:20:00

Hystrix微服務架構

2011-06-30 18:23:08

2017-03-21 23:29:44

DevOps運維開發

2023-09-26 07:57:17

C#.NetCCtor函數

2023-04-20 16:55:22

區塊鏈數組貨幣

2023-11-05 10:52:54

DNS服務器瀏覽器

2024-02-04 00:01:00

云原生技術容器

2025-01-15 13:30:48

FeignHTTPJava

2021-07-23 10:11:33

物聯網IOT

2025-04-02 01:22:44

MySQL樂觀鎖數據

2019-07-29 07:29:05

2020-12-17 17:40:01

物聯網智能IOT

2024-06-24 00:07:00

開源es搜索引擎

2024-01-11 08:53:58

2021-09-27 08:02:17

CDN加速網站網絡

2020-06-08 12:47:08

ETLHadoopSpark

2009-07-07 16:50:39

ServletResp
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜男人视频 | 日韩中文字幕在线播放 | 中文字幕免费中文 | 亚洲视频1区 | 人人草人人干 | 免费毛片网站 | 99成人| 亚洲国产精品精华素 | 国产成人久久精品一区二区三区 | 久久久久国产精品一区二区 | 日韩欧美三区 | 欧美高清视频 | 亚洲成人精品视频 | 手机在线不卡av | 欧美精品在线免费观看 | www.99热.com| 久久精品亚洲精品国产欧美 | 国产精品xxxx| 狠狠久久| 国产亚洲精品久久久久动 | 欧美精品一区在线 | 在线视频一区二区三区 | 午夜精品视频在线观看 | 日韩免费一二三区 | 久久久久国产精品一区三寸 | 久久久久1 | 黄色大片网站 | 人人九九精 | 天天操夜夜看 | 亚洲精品精品 | 日韩在线中文字幕 | 九九热在线免费视频 | 久久99精品久久久久婷婷 | 免费视频一区 | 伊人手机在线视频 | 国产精品久久久久久238 | 国产一区二区视频在线观看 | 国产黄色大片在线观看 | 欧美日韩在线一区二区 | 九九热这里只有精品在线观看 | 国产精品久久久久久久久大全 |