• AtomicInteger


    1、开始
    public class AtomicInteger extends Number implements java.io.Serializable
    继承了类Number,实现了接口Serializable(可序列化)
    
    2、属性
    
        // setup to use Unsafe.compareAndSwapInt for updates
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        //用来记录value本身在内存中的内存地址,这个记录,也主要是为了在更新操作在内存中找到value的位置,方便比较。
        private static final long valueOffset;
    
        static {
          try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
          } catch (Exception ex) { throw new Error(ex); }
        }
    
        //用来存储当前的值,声明为volatile,是为了保证在更新操作时,当前线程可以拿到value的最新的值(并发情况下,value可能已经被其他线程更新了)
        private volatile int value;
    
    3、构造器
        public AtomicInteger(int initialValue) {
            value = initialValue;
        }
    
        public AtomicInteger() {
        }
    
    4、方法
    
    
        public final int get() {
            return value;
        }
    
        public final void set(int newValue) {
            value = newValue;
        }
    
        public final int getAndSet(int newValue) {
            for (;;) {
                //获取在当前线程中的值
                int current = get();
                if (compareAndSet(current, newValue))
                    return current;
            }
        }
    
        public final boolean compareAndSet(int expect, int update) {
            //使用unsafe的本地方法,实现高效的硬件级别CAS
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }
    
        public final boolean weakCompareAndSet(int expect, int update) {
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }
    
    5、注意
    1)、CAS是Compare and Swap的意思,比较并交换。CAS是乐观锁技术,是一个非阻塞的算法,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能够更新成功,而其他的线程都会失败,失败的线程并不会被挂起,而是被告知此次竞争失败,并可以再次尝试。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B,当且仅当预期值A和内存值V相等时,将内存值V修改为B,否则什么都不做。
    2)、CAS操作中,会出现ABA问题。由于CAS需要在操作的时候检查下值是否发生了变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,最后又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却发生了变化。ABA问题的解决思路就是使用版本号,在变量前面追加上版本号,每次变量更新的时候把版本号加1,那么A-B-A,就会变成1A-2B-3C。
    ABA问题:若其中一个线程修改A-B-A,另外一个线程仍然读取到A,虽然值是预期值,但并不能说明该内存值没有变化。
    
    可以使用AtomicStampedReference解决ABA问题,使之执行CAS失败
    
    
    参考资料:
    http://my.oschina.net/magicly007/blog/364102
    http://www.importnew.com/20472.html
  • 相关阅读:
    JVM垃圾收集器以及内存分配
    VisualVM工具的使用
    jstack的使用
    内存溢出的定位与分析
    JVM的内存模型
    JVM运行参数
    kafka-高效读写数据+zookeeper作用+事务
    重定向机制
    HTTP协议、时间戳
    TCP常见面试题 
  • 原文地址:https://www.cnblogs.com/xiaoxian1369/p/5642916.html
Copyright © 2020-2023  润新知