Java中關於atomic的理解及使用示例


atomic對於數據原子性操作較方便處理,即當多個線程對同一個變量進行更新時,僅有一個線程可以成功,而未能成功的形成會像自旋鎖一樣,繼續嘗試,一直等到執行成功。

原子性原理:

 
 一、i++的原子性,i++的操作,分為三部分:"讀-改-寫"
            int i = 10;
            i = i++; //10
       
            int temp = i;
            i = i + 1;
            i = temp;
       
 二、原子變量:java.util.concurrent.atomic包下提供了常用的原子變量
           1.volatile 保證內存可見性
           2.CAS(Compare-And-Swap)算法保證數據的原子性
             CAS算法是硬件對於並發操作共享數據的支持。
             CAS包含了三個操作數:
                內存值:V
                預估值:A
                更新值:B
                當且僅當V == A, V = B,否則,不做任何操作。

嗯~~~理解以及使用直接上代碼………………

3 import java.util.concurrent.atomic.AtomicInteger;
  4 import java.util.function.DoubleUnaryOperator;
  5 import java.util.function.IntUnaryOperator;
  6 import static java.lang.Float.*;
  7 
  8 public class AtomicPrac {
  9     public static void main(String[] args) {
 10         AtomicDemo atomicDemo = new AtomicDemo();
 11         atomicDemo.setNumberA(new AtomicInteger(3));
 12         for (int i = 1; i <= 10; i++) {
 13             new Thread(atomicDemo).start();
 14         }
 15         
 16         AtomicInteger j=new AtomicInteger(4);
 17         System.out.println(j.incrementAndGet());
 18         System.out.println(updateAndGetInt(j,p -> p/2 ));
 19         
 20         //double型數據
 21         AtomicFloat k = new AtomicFloat(5);
 22         System.out.println(updateAndGetDouble(k,p -> p/2 ));
 23         
 24     }
 25     //模擬底層實現:
 26     public static float updateAndGetDouble(AtomicFloat i, DoubleUnaryOperator operator){
 27         while(true){
 28             float prev=i.get();//得到當前值
 29             float next=(float) operator.applyAsDouble(prev);//將舊值傳入,讓接口的某個方法完成具體運算,返回計算結果
 30             //重寫compareAndSet
 31             if(i.compareAndSet(prev,next)){
 32                 return next;
 33             }
 34         }
 35     }
 36     public static int updateAndGetInt(AtomicInteger i, IntUnaryOperator operator){
 37         while(true){
 38             int prev=i.get();//得到當前值
 39             int next=operator.applyAsInt(prev);//將舊值傳入,讓接口的某個方法完成具體運算,返回計算結果
 40             if(i.compareAndSet(prev,next)){
 41                 return next;
 42             }
 43         }
 44     }
 45     //模擬底層實現:
 46 }
 47 class AtomicDemo implements Runnable {
 48     public AtomicInteger numberA;
 49     
 50     public void run() {
 51         try {
 52               Thread.sleep(200);
 53         } catch (InterruptedException e) {
 54               e.printStackTrace();
 55         }
 56           System.out.println(Thread.currentThread().getName() + ":" + getNumberA());
 57     }
 58 
 59     public int getNumberA() {
 60         return numberA.updateAndGet(x -> x*2);
 61     }
 62 
 63     public void setNumberA(AtomicInteger numberA) {
 64         this.numberA = numberA;
 65     }
 66 }
 67 
 68 //對於使用雙精度型的數據對應AtomicLong 自定義AtomicDouble   轉換doubleToLongBits(1.00);
 69 //對於使用單精度型的數據對應AtomicInteger 自定義AtomicFloat   轉換floatToIntBits(1.00);
 70 class AtomicFloat extends Number {
 71     
 72     private AtomicInteger bits;
 73     
 74     public AtomicFloat() {
 75         this(0f);
 76     }
 77     
 78     public AtomicFloat(float initialValue) {
 79         bits = new AtomicInteger(floatToIntBits(initialValue));
 80     }
 81     
 82     public final boolean compareAndSet(float expect, float update) {
 83         return bits.compareAndSet(floatToIntBits(expect),
 84                 floatToIntBits(update));
 85     }
 86     
 87     public final void set(float newValue) {
 88         bits.set(floatToIntBits(newValue));
 89     }
 90     
 91     public final float get() {
 92         return intBitsToFloat(bits.get());
 93     }
 94     
 95     public float floatValue() {
 96         return get();
 97     }
 98     
 99     public final float getAndSet(float newValue) {
100         return intBitsToFloat(bits.getAndSet(floatToIntBits(newValue)));
101     }
102     
103     public final boolean weakCompareAndSet(float expect, float update) {
104         return bits.weakCompareAndSet(floatToIntBits(expect),
105                 floatToIntBits(update));
106     }
107     
108     public double doubleValue() { return (double) floatValue(); }
109     public int intValue()       { return (int) get();           }
110     public long longValue()     { return (long) get();          }
111 }

運行結果:

5
2
2.5
Thread-0:6
Thread-1:12
Thread-4:24
Thread-9:192
Thread-8:384
Thread-3:768
Thread-2:96
Thread-5:48
Thread-6:3072
Thread-7:1536


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM