AtomicReference

AtomicReference类提供了一个能够原子读写的对象援用变量。 原子意味着尝试更改雷同AtomicReference的多个线程(例如,应用比拟和替换操作)不会使AtomicReference最终达到不统一的状态。 AtomicReference甚至有一个先进的compareAndSet()办法,它能够将援用与预期值(援用)进行比拟,如果它们相等,则在AtomicReference对象内设置一个新的援用。

AtomicStampReference 平安的批改一个变量的值

package com.keytech.task;import org.junit.platform.commons.logging.LoggerFactory;import java.util.concurrent.atomic.AtomicInteger;import java.util.concurrent.atomic.AtomicReference;/** * @className: AtomicIntegerTest * @description: TODO 类形容 * @author: mac * @date: 2020/12/29 **///线程平安public class AtomicIntegerTest {    private static AtomicReference<Integer> count=new AtomicReference<>(0);    public static void main(String[] args) {        //如果期望值是0,则批改成2        count.compareAndSet(0, 2); //ok        //如果期望值是1,则批改成4        count.compareAndSet(1, 4); //no ok        //如果期望值是2,则批改成8        count.compareAndSet(2, 8); //ok        System.out.println(count.get());    }}//输入8

如果AtomicReference<T>T是一个自定义的对象,线程平安?

public class AtomicReference<V> implements java.io.Serializable {    private static final long serialVersionUID = -1848883965231344442L;    private static final Unsafe unsafe = Unsafe.getUnsafe();    private static final long valueOffset;    static {        try {            valueOffset = unsafe.objectFieldOffset                (AtomicReference.class.getDeclaredField("value"));        } catch (Exception ex) { throw new Error(ex); }    }    private volatile V value;    /**     * Creates a new AtomicReference with the given initial value.     *     * @param initialValue the initial value     */    public AtomicReference(V initialValue) {        value = initialValue;    }    /**     * Creates a new AtomicReference with null initial value.     */    public AtomicReference() {    }    /**     * 不须要平安防护     */    public final V get() {        return value;    }    /**     * 设值值不须要进行对象平安防护     */    public final void set(V newValue) {        value = newValue;    }    /**     * 很显著调用的是csa操作     * 比拟对象是否雷同,进行设值     * 设值胜利返回true,否则返回false     */    public final boolean compareAndSet(V expect, V update) {        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);    }    /**     * 设置新的值并且返回旧的值     * 原子操作     */    @SuppressWarnings("unchecked")    public final V getAndSet(V newValue) {        return (V)unsafe.getAndSetObject(this, valueOffset, newValue);    }}
compareAndSet采纳CAS保障并发

AtomicReference 所提供的某些办法能够进行原子性操作,如compareAndSet、getAndSet,这仅仅是对援用进行原子性操作

AtomicReference 不能保障对象中若存在属性值批改是线程平安的,如假如援用对象是person,批改person中name和age,多个线程同时从援用中取得对象,并进行批改,会呈现线程不平安状况。上面咱们通过代码来验证一下这条论断。

AtomicReference不平安的批改自定义对象属性的值

package com.keytech.task;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;import java.util.concurrent.atomic.AtomicReference;/** * @className: AtomicReferenceTest * @description: TODO 类形容 * @author: mac * @date: 2020/12/29 **/public class AtomicReferenceTest {    private static Integer clientTotal=5000;    private static Integer threadTotal=200;    private static Rumenz rumenz=new Rumenz(0,0);    private static AtomicReference<Rumenz> rumenzReference=new AtomicReference<>(rumenz);    public static void main(String[] args) {        ExecutorService executorService = Executors.newCachedThreadPool();        Semaphore semaphore=new Semaphore(threadTotal);        for (int i = 0; i < clientTotal; i++) {            final  Integer n=i;            executorService.execute(()->{                 try{                    semaphore.acquire();                     update(n);                    semaphore.release();                 }catch (Exception e){                     e.printStackTrace();                 }            });        }        executorService.shutdown();        System.out.println("rumenzReference="+rumenzReference.get().getAge()); System.out.println("rumenzReference="+rumenzReference.get().getName());    }    //如果线程平安的话,age的值和name的值是统一的    //如果线程不平安的话,age的值和name是不一样的。    private static void update(int i){        rumenzReference.get().setAge(rumenzReference.get().getAge()+i);        rumenzReference.get().setName(rumenzReference.get().getName()+i);    }}class Rumenz{    private Integer age;    private Integer name;    public Rumenz(Integer age, Integer name) {        this.age = age;        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    public Integer getName() {        return name;    }    public void setName(Integer name) {        this.name = name;    }}
在低并发状况下能够失去正确的后果,然而高并发状况下就会呈现差别.因为自定义的对象在拜访时用的是set,get没有CAS,所以导致线程不平安.

通过AtomicintegerFieldUpdater平安的批改自定义对象

atomic包中提供AtomicReferenceFieldUpdaterAtomicIntegerFieldUpdaterAtomicLongFieldUpdater,原子性的更新某一个类实例的指定的某一个字段.

AtomicIntegerFieldUpdater

通过CAS批改变量值
package com.keytech.task;import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;/** * @className: AtomicIntegerFieldUpdaterTest * @description: TODO 类形容 * @author: mac * @date: 2020/12/29 **/public class AtomicIntegerFieldUpdaterTest {    private static AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> upCount=AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdaterTest.class,"count");    public int getCount() {        return count;    }    public volatile int count=100;    public static void main(String[] args) {        AtomicIntegerFieldUpdaterTest obj=new AtomicIntegerFieldUpdaterTest();        if(upCount.compareAndSet(obj,100,200)){            System.out.println("批改胜利"+obj.getCount());        }        if(upCount.compareAndSet(obj,100,200)){            System.out.println("批改胜利");        }else{            System.out.println("批改失败");        }    }}//批改胜利200//批改失败

AtomicIntegerFieldUpdater源码剖析

public abstract class AtomicIntegerFieldUpdater<T> {    /**     *     * @param tclass 持有某字段的类     * @param fieldName 字段名字     */    @CallerSensitive    public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,                                                              String fieldName)     {        return new AtomicIntegerFieldUpdaterImpl<U>            (tclass, fieldName, Reflection.getCallerClass());    }        /**     * 原子性设置     */    public int getAndSet(T obj, int newValue) {        int prev;        do {            prev = get(obj);        } while (!compareAndSet(obj, prev, newValue));        return prev;    }        private static class AtomicIntegerFieldUpdaterImpl<T>            extends AtomicIntegerFieldUpdater<T> {        private static final Unsafe unsafe = Unsafe.getUnsafe();        private final long offset;        private final Class<T> tclass;        private final Class<?> cclass;        AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,                                      final String fieldName,                                      final Class<?> caller) {            final Field field;            final int modifiers;            try {                field = AccessController.doPrivileged(                    new PrivilegedExceptionAction<Field>() {                        public Field run() throws NoSuchFieldException {                            //字段不存在会抛异样                            return tclass.getDeclaredField(fieldName);                        }                    });                 //查看拜访级别                modifiers = field.getModifiers();                sun.reflect.misc.ReflectUtil.ensureMemberAccess(                    caller, tclass, null, modifiers);                ClassLoader cl = tclass.getClassLoader();                ClassLoader ccl = caller.getClassLoader();                if ((ccl != null) && (ccl != cl) &&                    ((cl == null) || !isAncestor(cl, ccl))) {                  sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);                }            } catch (PrivilegedActionException pae) {                throw new RuntimeException(pae.getException());            } catch (Exception ex) {                throw new RuntimeException(ex);            }            Class<?> fieldt = field.getType();            //必须是int            if (fieldt != int.class)                throw new IllegalArgumentException("Must be integer type");            //必须用volatile润饰            if (!Modifier.isVolatile(modifiers))                throw new IllegalArgumentException("Must be volatile type");            this.cclass = (Modifier.isProtected(modifiers) &&                           caller != tclass) ? caller : null;            this.tclass = tclass;            //用Unsafe里的那一坨办法去原子更新            offset = unsafe.objectFieldOffset(field);        }    }}

AtomicIntegerFieldUpdater线程平安的更新自定义对象的属性值

package com.keytech.task;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;/** * @className: AtomicReferenceTest * @description: TODO 类形容 * @author: mac * @date: 2020/12/29 **/public class AtomicReferenceTest {    private static Integer clientTotal=5000;    private static Integer threadTotal=200;    public static Rumenz rumenz=new Rumenz(0,0);    public static AtomicIntegerFieldUpdater<Rumenz> rumenzReferenceAge= AtomicIntegerFieldUpdater.newUpdater(Rumenz.class,"age");   private static AtomicIntegerFieldUpdater<Rumenz> rumenzReferenceName= AtomicIntegerFieldUpdater.newUpdater(Rumenz.class,"name");    public static void main(String[] args) {        ExecutorService executorService = Executors.newCachedThreadPool();        Semaphore semaphore=new Semaphore(threadTotal);        for (int i = 0; i < clientTotal; i++) {            final  Integer n=i;            executorService.execute(()->{                 try{                    semaphore.acquire();                     update(n);                    semaphore.release();                 }catch (Exception e){                     e.printStackTrace();                 }            });        }        executorService.shutdown();        System.out.println("rumenzReference="+ rumenz.getAge());        System.out.println("rumenzReference="+ rumenz.getName());    }    public static void update(int i){        rumenzReferenceAge.incrementAndGet(rumenz);        rumenzReferenceName.incrementAndGet(rumenz);    }}class Rumenz{    //必须加volatile 如果是整数不能写包装类型:如不能为Integer    public volatile  int age;    public volatile  int name;    public Rumenz(Integer age, Integer name) {        this.age = age;        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }    public Integer getName() {        return name;    }    public void setName(Integer name) {        this.name = name;    }}//rumenzReference=5000//rumenzReference=5000