国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

【實戰Java高并發程序設計3】帶有時間戳的對象引用:AtomicStampedReference

2019-11-14 14:51:08
字體:
來源:轉載
供稿:網友

【實戰java高并發程序設計 1】Java中的指針:Unsafe類

【實戰Java高并發程序設計 2】無鎖的對象引用:AtomicReference

 AtomicReference無法解決上述問題的根本是因為對象在修改過程中,丟失了狀態信息。對象值本身與狀態被畫上了等號。因此,我們只要能夠記錄對象在修改過程中的狀態值,就可以很好的解決對象被反復修改導致線程無法正確判斷對象狀態的問題。

AtomicStampedReference正是這么做的。它內部不僅維護了對象值,還維護了一個時間戳(我這里把它稱為時間戳,實際上它可以使任何一個整數,它使用整數來表示狀態值)。當AtomicStampedReference對應的數值被修改時,除了更新數據本身外,還必須要更新時間戳。當AtomicStampedReference設置對象值時,對象值以及時間戳都必須滿足期望值,寫入才會成功。因此,即使對象值被反復讀寫,寫回原值,只要時間戳發生變化,就能防止不恰當的寫入。

AtomicStampedReference的幾個API在AtomicReference的基礎上新增了有關時間戳的信息:

//比較設置 參數依次為:期望值 寫入新值 期望時間戳 新時間戳public boolean compareAndSet(V expectedReference,V  newReference,int expectedStamp,int newStamp)//獲得當前對象引用public V getReference()//獲得當前時間戳public int getStamp()//設置當前對象引用和時間戳public void set(V newReference, int newStamp)

有了AtomicStampedReference這個法寶,我們就再也不用擔心對象被寫壞啦!現在,就讓我們使用AtomicStampedReference在修正那個貴賓卡充值的問題的:

 

01 public class AtomicStampedReferenceDemo {02 static AtomicStampedReference<Integer> money=new AtomicStampedReference<Integer>(19,0);03    public staticvoid main(String[] args) {04        //模擬多個線程同時更新后臺數據庫,為用戶充值05        for(int i = 0 ; i < 3 ; i++) {06            final int timestamp=money.getStamp();07             newThread() {  08                public void run() { 09                    while(true){10                        while(true){11                             Integerm=money.getReference();12                             if(m<20){13                          if(money.compareAndSet(m,m+20,timestamp,timestamp+1)){14           System.out.);15                                     break;16                                 }17                             }else{18                                //System.out.println("余額大于20元,無需充值");19                                 break ;20                             }21                        }22                    }23                } 24            }.start();25         }26        27        //用戶消費線程,模擬消費行為28        new Thread() { 29             publicvoid run() { 30                for(int i=0;i<100;i++){31                    while(true){32                        int timestamp=money.getStamp();33                        Integer m=money.getReference();34                        if(m>10){35                             System.out.println("大于10元");36                          if(money.compareAndSet(m, m-10,timestamp,timestamp+1)){37                       System.out.println("成功消費10元,余額:"+money.getReference());38                                 break;39                             }40                        }else{41                            System.out.println("沒有足夠的金額");42                             break;43                        }44                    }45                    try {Thread.sleep(100);} catch (InterruptedException e) {}46                 }47             } 48        }.start(); 49    }50 }
第2行,我們使用AtomicStampedReference代替原來的AtomicReference。第6行獲得賬戶的時間戳。后續的贈予操作以這個時間戳為依據。如果贈予成功(13行),則修改時間戳。使得系統不可能發生二次贈予的情況。消費線程也是類似,每次操作,都使得時間戳加1(36行),使之不可能重復。

執行上述代碼,可以得到以下輸出:

 

余額小于20元,充值成功,余額:39元大于10元成功消費10元,余額:29大于10元成功消費10元,余額:19大于10元成功消費10元,余額:9沒有足夠的金額可以看到,賬戶只被贈予了一次。

【實戰Java高并發程序設計 1】Java中的指針:Unsafe類

【實戰Java高并發程序設計 2】無鎖的對象引用:AtomicReference

 

 

摘自:實戰Java高并發程序設計


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 广德县| 青州市| 松溪县| 金乡县| 大连市| 甘谷县| 确山县| 漳州市| 合作市| 东兰县| 吉安县| 冷水江市| 祁阳县| 荣昌县| 平罗县| 昂仁县| 江川县| 勐海县| 嘉鱼县| 安陆市| 讷河市| 泽州县| 潜山县| 宜兰县| 汉川市| 合山市| 双流县| 玛纳斯县| 修水县| 赫章县| 萝北县| 探索| 清水县| 大理市| 茂名市| 中宁县| 家居| 玉环县| 和静县| 宁武县| 光山县|