原子类概览

 
Java SDK 并发包里提供的原子类内容很丰富,我们可以将它们分为五个类别:原子化的基本数据类型、原子化的对象引用类型、原子化数组、原子化对象属性更新器和原子化的累加器。这五个类别提供的方法基本上是相似的,并且每个类别都有若干原子类,你可以通过下面的原子类组成概览图来获得一个全局的印象。
 
1. 原子化的基本数据类型
 
相关实现有 AtomicBoolean、AtomicInteger 和 AtomicLong,提供的方法主要有以下这些
 1 getAndIncrement()    //    原子化    i++
 2 getAndDecrement()    //    原子化的    i--
 3 incrementAndGet()    //    原子化的    ++i
 4 decrementAndGet()    //    原子化的    --i
 5 //当前值+=delta,返回 += 前的值
 6 getAndAdd(delta)    
 7 //当前值 +=delta,返回 +=  后的值
 8 addAndGet(delta)
 9 //CAS操作,返回是否成功
10 compareAndSet(expect, update)
11 //以下四个⽅法
12 //新值可以通过传 func  函数来计算
13 getAndUpdate(func)
14 updateAndGet(func)
15 getAndAccumulate(x,func)
16 accumulateAndGet(x,func)

2.原子类底层用的是CAS自旋锁方案

打开任何一个源码,我们发现底层用的是unsafe的方法,而unsafe的方法又是被native修饰的,被native关键字修饰的方法叫做本地方法,本地方法和其它方法不一样,本地方法意味着和平台有关,另外native方法在JVM中运行时数据区也和其它方法不一样,它有专门的本地方法栈。native方法主要用于加载文件和动态链接库,由于Java语言无法访问操作系统底层信息(比如:底层硬件设备等),这时候就需要借助C语言来完成了。被native修饰的方法可以被C语言重写。

CAS中有经典的ABA问题,可参考之前的文章:CAS中的ABA问题 https://www.cnblogs.com/amberJava/p/12390939.html

实际上是用 AtomicStampedReference 和 AtomicMarkableReference 这两个原子类可以解决 ABA 问题

三、你可以编写自己原子类     

根据上面的类结构图,使用 AtomicReference即可

public class SpinLock {

  private AtomicReference<Thread> sign =new AtomicReference<>();

  public void lock(){
    Thread current = Thread.currentThread();
    while(!sign .compareAndSet(null, current)){
    }
  }

  public void unlock (){
    Thread current = Thread.currentThread();
    sign .compareAndSet(current, null);
  }
}
==========================================================================           如果您觉得这篇文章对你有帮助,可以【关注我】或者【点赞】,希望我们一起在架构的路上,并肩齐行
==========================================================================
原文地址:https://www.cnblogs.com/amberJava/p/12390959.html