JUC---atomic包中类的使用

目录

1CAS

1.1 CAS定义

1.2 CAS优势

1.3 CAS局限

1.4 CAS解决ABA:AtmoicStampRefenence

2 Atomic:(以AtomicInteger为例)2.1 AtomicInteger解决原子性问题代码:

2.2 AtomicInteger源码

3 AtmoicStampRefenence

3.1 AtmoicStampRefenence解决ABA实例代码:

3.2 AtmoicStampRefenenc源码

4. AtomicXXFieldUpdater(以AtomicIntegerFieldUpdater为例)

4.1 AtomicIntegerFieldUpdater 局限

4.1.1 不能访问对象的私有属性;4.1.2 访问的对象为null;4.1.3 field类型不匹配4.1.4 field必须是voletile

4.2 AtomicIntegerFieldUpdater使用场景:

4.2.1 让对象的属性操作具备原子性;4.2.2 保证对象的某个属性的原子性,而不是整个对象,减少内存消耗;4.2.3 避免使用Synchronized等重量级锁

4.3 AtomicIntegerFieldUpdater实例代码

4.4 AtomicIntegerFieldUpdater源码


1CAS

1.1 CAS定义

定义:compare and swap比较再交换


1.2 CAS优势

优势:CPU级别的同步指令,对于应用来说,相当于无锁。


1.3 CAS局限

局限:无法解决ABA问题


1.4 CAS解决ABA:AtmoicStampRefenence

2 Atomic:(以AtomicInteger为例)
​​​​​​​
2.1 AtomicInteger解决原子性问题代码:

AtomicInteger是基于CAS,无法解决ABA问题

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicTest {

    public static int version = 1;
    public static int num = 1;
    public static volatile int state = 0;

    public static void main(String[] args) throws Exception {

        //原子性:一个操作或者多个操作要么全部执行并且过程中不被打断,要么全部不执行
        //解决原子性问题
      AtomicInteger atomicInteger2 = new AtomicInteger(0);
        new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                atomicInteger2.getAndAdd(1);
                atomicInteger2.getAndAdd(-1);
                atomicInteger2.getAndAdd(1);
                System.out.println(Thread.currentThread().getName() + ":" + atomicInteger2.get());
            }
        }, "thread1").start();

        new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                atomicInteger2.getAndAdd(1);
                System.out.println(Thread.currentThread().getName() + ":" + atomicInteger2.get());
            }
        }, "thread2").start();

        Thread.sleep(2000);
        //volatile修饰的变量无法解决原子性问题;中间state可能会出现同值问题(多运行几次)
        new Thread(() -> {
            try{

                for (int i = 0; i < 100; i++) {
                    state++;
                    state--;
                    state++;
                    System.out.println(Thread.currentThread().getName() + ":" + state);
                }
            }catch (Exception e){
            }
        }, "thread3").start();
        new Thread(() -> {
            try{
                for (int i = 0; i < 100; i++) {
                    state++;
                    System.out.println(Thread.currentThread().getName() + ":" + state);
                }
            }catch (Exception e){
            }
        }, "thread4").start();

2.2 AtomicInteger源码

//AtomicInteger源码 
//构造方法  
    private volatile int value;
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }
//getAndSet 基于CAS机制
 public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    } 

3 AtmoicStampRefenence

3.1 AtmoicStampRefenence解决ABA实例代码:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicTest {

    public static int version = 1;
    public static int num = 1;
    public static volatile int state = 0;

    public static void main(String[] args) throws Exception {

//无法解决ABA问题
        AtomicInteger atomicInteger = new AtomicInteger(1);
        new Thread(()->{
            try{
                TimeUnit.SECONDS.sleep(2);
                atomicInteger.getAndAdd(1);
                System.out.println(Thread.currentThread().getName()+":"+atomicInteger.get());
            }catch (Exception e){
            }
        },"thread1").start();

        new Thread(()->{
            atomicInteger.getAndAdd(1);
            System.out.println(Thread.currentThread().getName()+":"+atomicInteger.get());
            atomicInteger.getAndAdd(-1);
            System.out.println(Thread.currentThread().getName()+":"+atomicInteger.get());
        },"thread2") .start();


        //能够解决ABA问题

       AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(num,version);

        int stamp = atomicStampedReference.getStamp();
        Thread.sleep(1000);
        new Thread(()->{
            try{
                try{

                    TimeUnit.SECONDS.sleep(2);
                   boolean flag =  atomicStampedReference.compareAndSet(num,++num,stamp,stamp+5);
                    System.out.println(Thread.currentThread().getName()+"的值:"+atomicStampedReference.getReference());
                    System.out.println(Thread.currentThread().getName()+"的版本:"+atomicStampedReference.getStamp());
                    System.out.println(flag);
                }catch (Exception e){

                }

            }catch (Exception e){
            }
        },"thread1").start();

        new Thread(()->{
            atomicStampedReference.compareAndSet(num,++num,version,++version);
            System.out.println(Thread.currentThread().getName()+"的版本:"+atomicStampedReference.getStamp());
            System.out.println(Thread.currentThread().getName()+"的值:"+atomicStampedReference.getReference());
            atomicStampedReference.compareAndSet(num,--num,version,++version);
            System.out.println(Thread.currentThread().getName()+"的值:"+atomicStampedReference.getReference());
            System.out.println(Thread.currentThread().getName()+"的版本:"+atomicStampedReference.getStamp());
        },"thread2") .start();

3.2 AtmoicStampRefenenc源码

//构造
   private volatile Pair<V> pair;
   public AtomicStampedReference(V initialRef, int initialStamp) {
        pair = Pair.of(initialRef, initialStamp);
    }
   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);
        }
    }
//compareAndSet 
    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)));
    }

4. AtomicXXFieldUpdater(以AtomicIntegerFieldUpdater为例)

4.1 AtomicIntegerFieldUpdater 局限

4.1.1 不能访问对象的私有属性;
4.1.2 访问的对象为null;
4.1.3 field类型不匹配
4.1.4 field必须是voletile

4.2 AtomicIntegerFieldUpdater使用场景:

4.2.1 让对象的属性操作具备原子性;
4.2.2 保证对象的某个属性的原子性,而不是整个对象,减少内存消耗;
4.2.3 避免使用Synchronized等重量级锁

4.3 AtomicIntegerFieldUpdater实例代码

import lombok.Data;

@Data
public class Student {
    volatile int age;
    //private int age; 不能是私有的,且必须是volatile修饰
    private String name;
}



import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicTest {

    public static void main(String[] args) throws Exception {
        //确保对象某个属性原子性
        AtomicIntegerFieldUpdater<Student> atomicIntegerFieldUpdater =  AtomicIntegerFieldUpdater.newUpdater(Student.class,"age");
        //对象不能为null,变量属性不能为私有,必须由volatile修饰,变量类型与AtomicXX对应的类型要一致
        Student student = new Student();
        student.setAge(1);
        atomicIntegerFieldUpdater.getAndAdd(student,1);
        System.out.println(atomicIntegerFieldUpdater.get(student));
    }
}

4.4 AtomicIntegerFieldUpdater源码

//创建  基于反射
   public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
                                                              String fieldName) {
        return new AtomicIntegerFieldUpdaterImpl<U>
            (tclass, fieldName, Reflection.getCallerClass());
    }

 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);
            }

            if (field.getType() != int.class)
                throw new IllegalArgumentException("Must be integer type");

            if (!Modifier.isVolatile(modifiers))
                throw new IllegalArgumentException("Must be volatile type");
            this.cclass = (Modifier.isProtected(modifiers) &&
                           tclass.isAssignableFrom(caller) &&
                           !isSamePackage(tclass, caller))
                          ? caller : tclass;
            this.tclass = tclass;
            this.offset = U.objectFieldOffset(field);
        }


//getAndAdd
    public int getAndAdd(T obj, int delta) {
        int prev, next;
        do {
            prev = get(obj);
            next = prev + delta;
        } while (!compareAndSet(obj, prev, next));
        return prev;
    }

           public final int get(T obj) {
            accessCheck(obj);//判断类型是否匹配
            return U.getIntVolatile(obj, offset);//基于CAS获取
        }


               private final void accessCheck(T obj) {
            if (!cclass.isInstance(obj))
                throwAccessCheckException(obj);
        }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值