08:线程安全之原子性操作

    竞太条件和临界区:(其实就是多线程访问相同资源的描述术语)
        多个线程访问了相同的资源,向这些资源执行了写操作,并对执行顺序有要求。就可能出现竞态条件。
        临界区:一段代码,如果在多线程执行的情况下,会对结果产生影响。那么这段代码就是临界区。
        竞态条件:是指多线程环境下竞争共享资源的情形。
    原子性操作:
        原子操作是一个步骤,或者多个步骤,但是执行顺序不能被打乱,也不能被切割而执行其中一部分。(不可中断)这样整个操作视为是原子的。
        将临界区转换成为原子性操作。保证线程安全。
    CAS机制:
        这是一个底层实现原子性的机制。
        Compare and swap 比较和交换,属于硬件原语,处理器提供的基本的内存操作的原子性
        CAS操作需要两个参数(旧值,新值):比较旧值然后更新新值。
        在操作的时候先比较旧值是否发生变化,如果已经发生了变化:说明别的线程已经对其修改了,不写入新值。
                                          如果没有发生变化:说明这个值没有变化,可以写入新值。
    J.U.C包提供了原子操作封装类:(其实是使用CAS机制实现的)
        AtomicBoolean:原子更新Boolean类型
        AtomicInteger:原子更新整型
        AtomicLong:原子更新长整型
        还有更新数组的、更新字段的、更新引用的。
        jdk1.8更新了:提供了效率更高的计数器。多线程时效率较高,适合频繁的更新但不频繁读取的场景。
            计数器:DoubleAdder、LongAdder
            更新器:DoubleAccumulator、LongAccumulator。(增强版的计数器,除了列加之外,还可以执行自定义的计算)
        例如,实现整数的自增:
         AtomicInteger i = new AtomicInteger(0);
         public void add(){
             // 底层使用Unsafe.class类实现。该类可以直接操作内存。实现CAS机制,从而保证了原子性。Unsafe可能出现平台兼容,不安全。
            i.incrementAndGet();
         }
    CAS的缺点:
        1:循环+CAS是的线程处于高频运转,资源浪费
        2:只针对单个变量,多个数据无法同时控制原子性。
原文地址:https://www.cnblogs.com/Xmingzi/p/12617367.html