zoukankan      html  css  js  c++  java
  • AtomicBoolean 源码分析

    AtomicBoolean

    AtomicBoolean 能解决什么问题?什么时候使用 AtomicBoolean?

    可原子更新的 boolean 值
    1)原子性:在Java中,对基本数据类型变量的读取和赋值操作是原子性操作,这些操作是不可被中断的,要么执行,要么不执行。
    2)可见性:当一个共享变量被 volatile修饰时,它会保证被修改的值会立即更新到主存中,当有其他线程需要读取时,它会去主存中读取新值。
    3)有序性:volatile 变量前后的指令不能执行交叉重排序,即 volatile 变量前的代码块总是比 volatile 变量后的代码块先执行。
    
    happens-before原则
    1)一个锁的 unlock 操作先行发生于后面对这个锁的 lock 操作。
    2)对一个 volatile 变量的写操作先行发生于后面对这个变量的读操作。
    3)如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C。
    4)Thread对象的start()方法先行发生于此线程的每个一个动作。
    5)一个对象的初始化完成先行发生于他的finalize()方法的开始。
    

    如何使用 AtomicBoolean?

    1)多个线程需要对指定的 boolean 值进行读写时,AtomicBoolean 相对于 synchronized 具有更高的吞吐量。
    

    使用 AtomicBoolean 有什么风险?

    1)高并发场景下,自旋 CAS 长时间失败会导致 CPU 飙升。
    

    AtomicBoolean 核心操作的实现原理?

    创建对象

        private static final VarHandle VALUE;
        static {
            try {
                final MethodHandles.Lookup l = MethodHandles.lookup();
                VALUE = l.findVarHandle(AtomicBoolean.class, "value", int.class);
            } catch (final ReflectiveOperationException e) {
                throw new Error(e);
            }
        }
    
        /**
         * 底层通过整数表示 boolean 值,1 表示 true,0 表示 false
         */
        private volatile int value;
    
        /**
         * 创建初始值为 initialValue 的 AtomicBoolean 实例
         */
        public AtomicBoolean(boolean initialValue) {
            value = initialValue ? 1 : 0;
        }
    
        /**
         * 创建初始值为 false 的 AtomicBoolean 实例
         */
        public AtomicBoolean() {
        }
    

    常用操作

        /**
         *  如果当前值为 expectedValue,则将其设置为 newValue,并返回 true,否则返回 false。
         *
         * @param expectedValue 期望值
         * @param newValue      新值
         */
        public final boolean compareAndSet(boolean expectedValue, boolean newValue) {
            return AtomicBoolean.VALUE.compareAndSet(this,
                    expectedValue ? 1 : 0,
                            newValue ? 1 : 0);
        }
    
        /**
         *  如果当前值为 expectedValue,则将其设置为 newValue,并返回设置前的原始值。
         *
         * @param expectedValue 期望值
         * @param newValue  新值
         * @return  原始值
         * @since 9
         */
        public final boolean compareAndExchange(boolean expectedValue, boolean newValue) {
            return (int)AtomicBoolean.VALUE.compareAndExchange(this,
                    expectedValue ? 1 : 0,
                            newValue ? 1 : 0) != 0;
        }
    
        /**
         * 读取值
         * with memory effects as specified by {@link VarHandle#getVolatile}.
         */
        public final boolean get() {
            return value != 0;
        }
    
        /**
         * 写入值
         * with memory effects as specified by {@link VarHandle#setVolatile}.
         */
        public final void set(boolean newValue) {
            value = newValue ? 1 : 0;
        }
    
        /**
         * 原子写入新值,并返回旧值
         */
        public final boolean getAndSet(boolean newValue) {
            return (int)AtomicBoolean.VALUE.getAndSet(this, newValue ? 1 : 0) != 0;
        }
    
        /**
         * 以写入普通变量的方式来修改共享状态,可以减少不必要的内存屏障,从而提高程序的执行效率,
         * 但是不保证立即被其他线程可见。
         * with memory effects as specified by {@link VarHandle#setRelease}.
         */
        public final void lazySet(boolean newValue) {
            AtomicBoolean.VALUE.setRelease(this, newValue ? 1 : 0);
        }
    
  • 相关阅读:
    Libgdx 截屏功能
    Tomcat+Spring+Quartz Restart or shutdown error
    JSP 基础知识
    Git 常用命令备忘
    Java 基础知识点
    Android adb 命令的基础知识
    在 Cygwin 环境下使用 linux 命令(2)
    Libgdx Pixmap 的使用
    Android 平台开发一些基础知识
    Cygwin 安装列表
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10055642.html
Copyright © 2011-2022 走看看