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