脚本宝典收集整理的这篇文章主要介绍了02-JUC-CAS,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
JUC中多数类是通过volatile和CAS来实现的,CAS本质上提供的是一种无锁方案,而Synchronized和Lock是互斥锁方案; java原子类本质上使用的是CAS,而CAS底层是通过Unsafe类实现的。
线程安全的方法有:
第一种方法是通过锁的方式来实现线程安全,CAS是通过无锁的方式实现的,下面重点说说CAS是如何实现线程安全的
就是有一个原值A, 如果要更新为值B,在更新前先比较原值A有没有发生变化,如果没有发生变化,就将A更新为值B,如果发生了变化就不交换
用AtomicInteger 举个小栗子:多线程情况下新增一个值
AtomicInteger a = new AtomicInteger(0); public int add(){ return a.addAndGet(1); }
synchronized是通过锁来保证线程安全的,是一种悲观锁策略
而CAS是一种乐观锁策略,但是在并发问题上性能更佳,它可能会出现的问题
我们上面提过,很多原子类是通过Unsafe实现的,
可以看一眼Unsafe类
public final class Unsafe { ...// 省略 public final int getAndAddInt(Object VAR1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.COMpareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; } public final long getAndAddLong(Object var1, long var2, long var4) { long var6; do { var6 = this.getLongVolatile(var1, var2); } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4)); return var6; } public final int getAndSetInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var4)); return var5; } public final long getAndSetLong(Object var1, long var2, long var4) { long var6; do { var6 = this.getLongVolatile(var1, var2); } while(!this.compareAndSwapLong(var1, var2, var6, var4)); return var6; } public final Object getAndSetObject(Object var1, long var2, Object var4) { Object var5; do { var5 = this.getObjectVolatile(var1, var2); } while(!this.compareAndSwapObject(var1, var2, var5, var4)); return var5; } ...//省略 }
可以发现,它是通过while自旋compareAndSwap进行CAS更新(如果失败就一直自旋)。里面的compareAndSwap* 都是底层的native方法
下面是Unsafe可以实现的功能(取自网络图)
比如,AtomicInteger就是通过Unsafe实现的原子性
public class AtomicInteger extends Number implements java.io.Serializable { PRivate static final long serialVersionUID = 6214790243416807050L; // SETUP to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; static { try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } // volatile 值 private volatile int value; /** * Creates a new AtomicInteger wITh the given initial value. * * @param initialValue the initial value */ public AtomicInteger(int initialValue) { value = initialValue; } ...//省略 public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue); } public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } public final boolean weakCompareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); } ...//省略 }
可以看到,value用了volatile来修饰,保证了线程的可见性,同时使用CAS来保证更新时的原子性
以上是脚本宝典为你收集整理的02-JUC-CAS全部内容,希望文章能够帮你解决02-JUC-CAS所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。