该文章为面试精华版,如果是初学者,建议学习专栏:Java并发专栏

Java并发需要结合JVM以及操作系统的相关知识,建议先学习这两个部分:JVM专栏操作系统专栏

一、CAS原理及缺陷

原理

  • CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。

  • 更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。

  • 从思想上来说,Synchronized属于悲观锁,悲观地认为程序中的并发情况严重,所以严防死守。

  • CAS属于乐观锁,乐观地认为程序中的并发情况不那么严重,所以让线程不断去尝试更新。

缺点

  1. 在竞争激烈的时候,CPU开销较大

在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很大的压力。

  1. 不能保证代码块的原子性

CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证多个变量共同进行原子性的更新,就不得不使用Synchronized了

二、ABA问题及解决

什么是ABA?

CAS的机制是在赋值的时候进行比较,如果此时的数值没有修改,则可以完成修改

但是,如果一个对象或者变量出现了:A => B => ...... => A,此时CAS算法进行比较,会没有任何问题,进行修改。但是此时可能已经被修改过了无数次,其他线程的修改就丢失了,在复杂的数据结构比如链表,队列,栈、树等都可能出现不可预知的问题

解决方式–AtomicStampedReference

  • 加一个版本号,除了比较对象值,还需要比较状态戳,类似于时间戳
  • 每次修改成功也会同时修改状态戳

三、atomic类

在高并发条件下,如果都需要对一些基本类型进行修改,就会破坏其原子性

Java并发包提供了一个原子类,基于的是用了 Unsafe 类的 CAS 操作

主要分为基本类型 、数组类型、引用类型和对象的属性子四类

四、Unsafe类

很多Java的基础类库,包括一些被广泛使用的高性能开发库都是基于Unsafe类开发的,比如Netty、Cassandra、Hadoop、Kafka等。Unsafe类在提升Java运行效率,增强Java语言底层操作能力方面起了很大的作用。

Java和C++语言的一个重要区别就是Java中我们无法直接操作一块内存区域,不能像C++中那样可以自己申请内存和释放内存。Java中的Unsafe类为我们提供了类似C++手动管理内存的能力,同时也有了指针的问题。