zoukankan      html  css  js  c++  java
  • Java多线程系列——原子类的实现(CAS算法)

      Java提供的原子类是靠 sun 基于 CAS 实现的,CAS 是一种乐观锁。关于乐观锁与悲观锁

      原子变量类相当于一种泛化的 volatile 变量,能够支持原子的和有条件的读-改-写操作。AtomicInteger 表示一个int类型的值,并提供了 get 和 set 方法,这些 Volatile 类型的int变量在读取和写入上有着相同的内存语义。它还提供了一个原子的 compareAndSet 方法(如果该方法成功执行,那么将实现与读取/写入一个 volatile 变量相同的内存效果),以及原子的添加、递增和递减等方法。AtomicInteger 表面上非常像一个扩展的 Counter 类,但在发生竞争的情况下能提供更高的可伸缩性,因为它直接利用了硬件对并发的支持。

    AtomicInteger的实现


      AtomicInteger 是一个支持原子操作的 Integer 类,就是保证对 AtomicInteger 类型变量的增加和减少操作是原子性的,不会出现多个线程下的数据不一致问题。如果不使用 AtomicInteger,要实现一个按顺序获取的 ID,就必须在每次获取时进行加锁操作,以避免出现并发时获取到同样的 ID 的现象。

      接下来通过源代码来看 AtomicInteger 具体是如何实现的原子操作。

      首先看 value 的声明:

    private volatile int value;

      volatile 修饰的 value 变量,保证了变量的可见性。

      incrementAndGet() 方法,下面是具体的代码:

    public final int incrementAndGet() {
            for (;;) {
                int current = get();
                int next = current + 1;
                if (compareAndSet(current, next))
                    return next;
            }
     }

      通过源码,可以知道,这个方法的做法为先获取到当前的 value 属性值,然后将 value 加 1,赋值给一个局部的 next 变量,然而,这两步都是非线程安全的,但是内部有一个死循环,不断去做 compareAndSet 操作,直到成功为止,也就是修改的根本在 compareAndSet 方法里面,compareAndSet()方法的代码如下:

    public final boolean compareAndSet(int expect, int update) {
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

      compareAndSet()方法调用的compareAndSwapInt()方法的声明如下,是一个native方法。 

    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, intvar5);

      compareAndSet 传入的为执行方法时获取到的 value 属性值,next 为加 1 后的值, compareAndSet 所做的为调用 Sun 的 UnSafe 的 compareAndSwapInt 方法来完成,此方法为 native 方法,compareAndSwapInt 基于的是 CPU 的 CAS 指令来实现的。所以基于 CAS 的操作可认为是无阻塞的,一个线程的失败或挂起不会引起其它线程也失败或挂起。并且由于 CAS 操作是 CPU 原语,所以性能比较好

      类似的,还有 decrementAndGet() 方法。它和 incrementAndGet() 的区别是将 value 减 1,赋值给next 变量。

          AtomicInteger 中还有 getAndIncrement() 和 getAndDecrement() 方法,他们的实现原理和上面的两个方法完全相同,区别是返回值不同,前两个方法返回的是改变之后的值,即 next。而这两个方法返回的是改变之前的值,即 current。还有很多的其他方法,就不列举了。

    CAS算法

    CAS(Compare-And-Swap)算法保证数据操作的原子性。

    CAS 算法是硬件对于并发操作共享数据的支持。

    CAS 包含了三个操作数:
      内存值 V
      预估值 A
      更新值 B

    当且仅当 V == A 时,V 将被赋值为 B,否则循环着不断进行判断 V 与 A 是否相等。

  • 相关阅读:
    精心总结的Linux运维面试题汇总
    [DevExpress]DxValidationProvider分享
    PivotGridField 中对Unbound的列赋值(除法)--数据钻取
    PivotGridField 中对Unbound的列赋值(除法)
    2020后端/前段开发工程师应当掌握的专业技能一览(源自github)
    跨域的CRUD
    水印图片和文字
    导入 导出 压缩 解压
    winForm的CRUD 加上传图片 的DAL
    winForm的CRUD 加上传图片
  • 原文地址:https://www.cnblogs.com/zhengbin/p/5657707.html
Copyright © 2011-2022 走看看