Java并发编程之CAS的案例分析

  介绍

这篇文章主要介绍Java并发编程之CAS的案例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

Java并在发编程的世界里,同步和锁是控制多线程并发环境下对共享资源同步访问的两大手段,其中锁是JDK层面的锁机制,是轻量级锁,底层使用大量的自旋+ CAS操作实现的。

那什么是中科院呢? CAS,比较和交换,即比较并交换,什么是比较并交换呢?在锁锁的理念中,采用的是一种乐观锁的形式,即多线程去修改共享资源时,不是在修改之前就加锁,而是乐观的认为没有别的线程和自己争锁,就是通过中科院的理念去保障共享资源的安全性的.CAS的基本思想的是,拿变量的原值和内存中的值进行比较,如果相同,则原值没有被修改过,那么就将原值修改为新值,这两步是原子的,能够保证同一时间只有一个线程修改成功。这就是中科院的理念。

Java中要想使用CAS原子的修改某值,怎么做呢?幸运的是Java提供了这样的API,就是在sun.misc.Unsafe。java类中.Unsafe,中文名不安全的,也被称为魔术类,魔法类。

<强>安全类介绍

安全类使java拥有了像C语言的指针一样操作内存空间的能力,一旦能够直接操作内存,这也就意味着

(1)不受JVM管理,意思就是使用安全操作内存无法被JVM GC,需要我们手动GC,稍有不慎就会出现内存泄漏。
(2)不安全的不少方法中必须提供原始地址(内存地址)和被替换对象的地址,并且偏移量要自己计算(其提供的有计算偏移量的方法),所以一旦出现问题就是JVM崩溃级别的异常,会导致整个JVM实例崩溃,表现为应用程序直接崩溃掉。
(3)直接操作内存,所以速度更快,在高并发的条件之下能够很好地提高效率。

因此,从上面三个角度来看,虽然在一定程度上提升了效率但是也带来了指针的不安全性。这也是它被取名为不安全的原因吧。

下面我们深入到源码中看看,提供了什么方法直接操作内存。

打开不安全这个类,我们会发现里面有大量的被本地关键字修饰的方法,这意味着这些方法是C语言提供的实现,底层调的是C语言的库函数,我们无法直接看到他的源码实现,需要去从OpenJDK去看了。另外还有一些基于本机方法封装的其他方法,整个不安全中的方法大致可以归结为以下几类:

(1)初始化操作
(2)操作对象属性
(3)操作数组元素
(4)线程挂起和恢复
(5)中科院机制

<强> CAS的使用

如果你学过java并发编程的话,稍微阅读过JUC并发包里面的源码的话,对这类个不安全一定不陌生,因为整个java并发包底层实现的核心就是靠它.JUC并发包中主要使用它提供的CAS(比较和交换,比较并交换)操作,原子的修改锁的状态和一些队列元素。

没看过JUC源码的读者也不用担心,今天我们就是简单介绍不安全类中的CAS操作,那么我们接下来就会通过一个简单的例子来看看不安全的CAS是怎么使用的。

首先,使用这个类我们第一个要做的事情就是拿到这个类的实例,下面我们自定义了一个实效类用来获取不安全的实例

进口sun.misc.Unsafe;
  进口java.lang.reflect.Field;
  
  公开课UnsafeUtil {
  公共静态安全reflectGetUnsafe () {
  尝试{
  字段字段=Unsafe.class.getDeclaredField (“theUnsafe");
  field.setAccessible(真正的);
  返回(不安全)field.get(空);
  }捕捉(异常e) {
  e.printStackTrace ();
  }
  返回null;
  }
  }

这个工具类通过反射的方式拿到不安全的类中的一个名为theUnsafe字段,该字段是不安全的类型,并在静态块中新的一个不安全的对象初始化这个字段(单例模式)。

然后我们定义了一个AtomicState类,这个类很简单,有一个int型的状态字段,还有一个不安全的常量,以及int型的offsetState,用来记录状态字段在AtomicState对象中的偏移量。具体代码如下:

进口com.walking.juc.util.UnsafeUtil;
  进口sun.misc.Unsafe;
  公开课AtomicState {
  私人int波动状态=0;
  公共int getState () {
  返回状态;
  }
  
  私有静态最终不安全不安全=UnsafeUtil.reflectGetUnsafe ();
  私有静态最终长offsetState;
  静态{
  尝试{
  offsetState=UNSAFE.objectFieldOffset (AtomicState.class.getDeclaredField (“state"));
  }捕捉(NoSuchFieldException e) {
  把新的错误(e);
  }
  }
  公共最终布尔compareAndSetState (int oldVal int newVal) {
  返回UNSAFE.compareAndSwapInt (offsetState, oldVal newVal);
  }
  }

Java并发编程之CAS的案例分析