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
包中提供AtomicReferenceFieldUpdater
、AtomicIntegerFieldUpdater
、AtomicLongFieldUpdater
,原子性的更新某一个类实例的指定的某一个字段.
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