cas解决aba,java中的cas机制的描述错误的是

  cas解决aba,java中的cas机制的描述错误的是

  00-1010 1.CAS 1) CAS概念2)CAS(无锁执行)的影响3)代码分析3)自动并发CAS原则4)CAS导致的ABA问题

  

目录

 

  

1.CAS

CAS是Compare and Swap的缩写,即Compare And Swap是用于实现多线程同步的原子指令。它将内存位置的内容与一个给定值进行比较,如果相同,它将内存位置的值修改为一个新值。整个操作是通过调用UnSafe的compareAndSwapObject、compareAndSwapInt或者compareAndSwapLong来完成的,这些方法都是原生的修改局部方法,是系统原语系统支持的操作。

 

  

1)CAS概念

CAS是没有锁的对象的原子操作。锁分为乐观锁和悲观锁。乐观主义者随意同意对象资源,几乎不修改同一资源。如果修改的是同一个资源,就不会修改成功,可以保证资源的安全性。悲观主义者会认为同样的资源被误修改后会造成不可挽回的局面,所以可以有一个线程来修改资源。这样总会对系统性能造成一定的影响,减缓自速度。CAS是无锁执行器。CAS修改的资源可以被多个线程同时修改,系统安全性仍然可以得到保证。不需要等待系统性能提升而不锁定。介绍了利用jdk提供的CAS原理实现并发类Automic系列的原理和应用。

 

  00-1010首先介绍java的指针操作类UnSafe。Unsafe类在sun.misc包下,不属于Java标准。但是Java的很多基础类库,包括一些广泛使用的高性能开发库,都是基于UnSafe类开发的,因为UnSafe使得Java具备了像C语言一样操作内存指针的能力,又因为操作内存指针容易出错,所以命名为Unsafe类,所以Java官方并不推荐。但是,CAS原则是通过UnSafe类中的compareAndSwapObject、compareAndSwapInt和compareAndSwapLong方法实现的。这个方法需要传入四个参数:第一个参数表示给定对象,第二个参数表示给定对象在内存中的偏移量,第三个参数标识对象的期望值,第四个参数标识要修改的值。被关注的Automic系列的原子操作类都是通过使用UnSafe类实现的。

  不安全的源代码如下:

  /* * *第一个参数var1表示给定对象,第二个参数var2表示var1对象在内存中的偏移量,第三个参数var3表示要修改对象的旧值*,第四个参数var4表示要修改的值或修改后的值。* */public final native boolean compareAndSwapObject(Object var 1,long var2,Object var3,Object var 4);public final native boolean compareAndSwapInt(Object var 1,long var2,int var4,int var 5);public final native boolean compareAndSwapLong(Object var 1,long var2,long var4,long var 6);举例AtomicInteger源码实现原理:

  自动集成器中getAndSet的实现原理分析:

  /* * * UnSafe的被调用的getAndSetInt方法,给定值、偏移量和修改值,*获取修改值var5作为compareAndSwapInt的第三个参数,与var1比较,然后执行更新操作* while循环知道操作成功。* public final int getAndSetInt(Object var 1,long var2,int var 4){ * int var 5;* do { * var 5=this . getint volatile(var 1,var 2);* } while(!this.compareAndSwapInt(var1,var2,var5,var 4));* *返回var5* } * */public final int getAndSet(int new value){ return unsafe . getandsetint(this,valueOffset,new value);}包Java . util . concurrent . atomic;导入Java . util . function . intunaryoperator;导入java.util

  .function.IntBinaryOperator;import sun.misc.Unsafe; public class AtomicInteger extends Number implements java.io.Serializable { private static final long serialVersionUID = 6214790243416807050L; // 获取UnSafe对象实例 private static final Unsafe unsafe = Unsafe.getUnsafe(); //对象在内存中的偏移量 private static final long valueOffset; //初始化valueOffset static { try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } //对象属性值 private volatile int value; public AtomicInteger(int initialValue) { value = initialValue; } public AtomicInteger() { } /** * 调用的UnSafe的getAndSetInt方法,给定值和偏移量和修改的值, * 获取修改的值var5作为compareAndSwapInt的第三个参数用来和var1比较相同则执行更新操作 * while循环知道操作成功。 *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 int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue); } //调用UnSafe的compareAndSwapInt方法保证CAS public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } //调用UnSafe的compareAndSwapInt方法保证CAS public final boolean weakCompareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } //调用UnSafe的getAndAddInt再调用UnSafe的getAndSetInt方法保证CAS public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); } public final int getAndDecrement() { return unsafe.getAndAddInt(this, valueOffset, -1); } .........}

 

  

4)CAS导致的ABA问题

操作对象,获取对象后,执行CAS操作前,被其他线程修改后,且又修改为原来的对象值,导致CAS忽略其他线程的修改,成功执行CAS对象修改,这种情况就叫做ABA问题。

 

  下图所示:

  

 

  解决办法:

  AtomicStampedReference类提供了解决办法,在对象之中又添加了stamp时间戳属性避免其他线程修改了多次并变回修改前的value值,但对比stamp不同便可知道对象是被修改过的,只有提供属性值和stamp时间戳相等才能成功执行CAS修改操作,里面包裹了一个键值对对象AtomicStampedReference.Pair<V> pair类型,pair中值为属性值,value为stamp时间戳,在执行CAS操作时需要提供原值的value和时间戳都相等的情况才能成功执行CAS操作。

  AtomicMarkableReference类提供了解决办法,在对象之中又添加了stamp时间戳属性避免其他线程修改了多次并变回修改前的value值,但对比stamp不同便可知道对象是被修改过的,只有提供属性值和boolean类型的mark标记相等才能成功执行CAS修改操作,里面包裹了一个键值对对象AtomicMarkableReference.Pair<V> pair类型,pair中值为属性值,value为mark是否被修改的标记,在执行CAS操作时需要提供原值的value和mark标记都相等的情况才能成功执行CAS操作。

  本文只介绍AtomicStampedReference类的源码分析,AtomicMarkableReference类同AtomicStampedReference类原理一样,

  源码如下:

  

package java.util.concurrent.atomic;public class AtomicStampedReference<V> { /** * 对象值时一个AtomicStampedReference内置对象Pair,包裹了reference和stamp两个属性 */ private static class Pair<T> { final T reference; final int stamp; private Pair(T reference, int stamp) { this.reference = reference; this.stamp = stamp; } static <T> Pair<T> of(T reference, int stamp) { return new Pair<T>(reference, stamp); } } private volatile Pair<V> pair; /** * 初始化对象并初始化pair */ public AtomicStampedReference(V initialRef, int initialStamp) { pair = Pair.of(initialRef, initialStamp); } /** * 比较当前对象属性值和输入原始值为真,在比较当前对象的时间stamp与期望的stamp进行比较 * 如果也想等,就更新值和stamp * @param expectedReference 原始值 * @param newReference 新值 * @param expectedStamp 期望时间 * @param newStamp 新时间 * @return {@code true} if successful */ public boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) { Pair<V> current = pair; //赋值当前对象 return expectedReference == current.reference && expectedStamp == current.stamp && ((newReference == current.reference && newStamp == current.stamp) casPair(current, Pair.of(newReference, newStamp))); } // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); private static final long pairOffset = objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class); private boolean casPair(Pair<V> cmp, Pair<V> val) { return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); } static long objectFieldOffset(sun.misc.Unsafe UNSAFE, String field, Class<?> klazz) { try { return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); } catch (NoSuchFieldException e) { // Convert Exception to corresponding Error NoSuchFieldError error = new NoSuchFieldError(field); error.initCause(e); throw error; } }}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持盛行IT。

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: