深刻浅出ConcurrentHashMap1.8+CAS+volatile

1.深刻浅出CASjava

前言

CAS(Compare and Swap),即比较并替换,实现并发算法时经常使用到的一种技术,Doug lea大神在java同步器中大量使用了CAS技术,鬼斧神工的实现了多线程执行的安全性。CAS原理(也能够理解为乐观锁)保证了原子面试

CAS的思想很简单:三个参数,一个当前内存值V、旧的预期值A、即将更新的值B,当且仅当预期值A和内存值V相同时,将内存值修改成B并返回true,不然什么都不作,并返回false。算法

CAS缺点

CAS存在一个很明显的问题,即ABA问题。数组

问题:若是变量V初次读取的时候是A,而且在准备赋值的时候检查到它仍然是A,那能说明它的值没有被其余线程修改过了吗?缓存

若是在这段期间曾经被改为B,而后又改回A,那CAS操做就会误认为它历来没有被修改过。针对这种状况,java并发包中提供了一个带有标记的原子引用类AtomicStampedReference,它能够经过控制变量值的版原本保证CAS的正确性。安全

2.volatile关键字数据结构

前言多线程

volatile做为java中的关键词之一,用以声明变量的值可能随时会别的线程修改,使用volatile修饰的变量会强制将修改的值当即写入主存,主存中值的更新会使缓存中的值失效(非volatile变量不具有这样的特性,非volatile变量的值会被缓存,线程A更新了这个值,线程B读取这个变量的值时可能读到的并非是线程A更新后的值)。volatile会禁止指令重排。并发

 

  2.1 volatile特性jvm

 

volatile具备可见性、有序性,不具有原子性。

 

注意,volatile不具有原子性,这是volatile与java中的synchronized、java.util.concurrent.locks.Lock最大的功能差别,这一点在面试中也是很是容易问到的点。

 

下面来分别看下可见性、有序性、原子性:

 

原子性:若是你了解事务,那这个概念应该好理解。原子性一般指多个操做不存在只执行一部分的状况,若是所有执行完成那没毛病,若是只执行了一部分,那对不起,你得撤销(即事务中的回滚)已经执行的部分。可见性:当多个线程访问同一个变量x时,线程1修改了变量x的值,线程一、线程2...线程n可以当即读取到线程1修改后的值。有序性:即程序执行时按照代码书写的前后顺序执行。在Java内存模型中,容许编译器和处理器对指令进行重排序,可是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。(本文不对指令重排做介绍,但不表明它不重要,它是理解JAVA并发原理时很是重要的一个概念)。3.volatile适用场景

 

适用于对变量的写操做不依赖于当前值,对变量的读取操做不依赖于非volatile变量。适用于读多写少的场景(由于读操做不须要原子性)可用做状态标志。JDK中volatie应用:JDK中ConcurrentHashMap的Entry的value和next被声明为volatile,AtomicLong中的value被声明为volatile。AtomicLong经过CAS原理(也能够理解为乐观锁)保证了原子性。    

  2.2 volatile VS synchronized

  • volatile本质是在告诉jvm当前变量在寄存器(工做内存)中的值是不肯定的,须要从主存中读取; synchronized则是锁定当前变量,只有当前线程能够访问该变量,其余线程被阻塞住。
  • volatile仅能使用在变量级别;synchronized则可使用在变量、方法、和类级别的
  • volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则能够保证变量的修改可见性和原子性
  • volatile不会形成线程的阻塞;synchronized可能会形成线程的阻塞。
  • volatile标记的变量不会被编译器优化;synchronized标记的变量能够被编译器优化

深刻浅出ConcurrentHashMap1.8  (转载 https://www.jianshu.com/p/c0642afe03e0)

对于上面的文章的总结

  1. jdk1.7 ConcurrentHashMap采用 分段锁的机制,实现并发的更新操做,底层采用数组+链表的存储结构,jdk1.8的实现已经抛弃了Segment分段锁机制,利用CAS+Synchronized来保证并发更新的安全,底层采用数组+链表+红黑树的存储结构。

  2. 键值对节点使用的Node

  • Node:保存key,value及key的hash值的数据结构。

 

其中value和next都用volatile修饰,保证并发的可见性。

3. put操做采用CAS+synchronized实现并发插入或更新操做

4.其余的和hashMap 差很少。

5.线程安全,不容许有null值null 键

相关文章
相关标签/搜索