JAVA锁中的CAS

Posted 厚积_薄发

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA锁中的CAS相关的知识,希望对你有一定的参考价值。

 一 .CAS

       在学习java.util.concurrent(简称JUC)包下的类时,了解到了CAS这个概念,整个JUC包的基础也是CAS,ReentrantLock也是基于它的。学习CAS,先从synchronized关键字说起,synchronized关键字能保证最基本的互斥同步。同步是指在多个线程并发访问共享数据时,保证共享数据在同一个时刻只被一个线程使用。而互斥是实现同步的一种手段。互斥同步4个字,互斥是因,同步是果;互斥是方法,同步是目的。互斥同步属于一种悲观的并发政策,认为如果不进行正确的同步措施,那就好出现问题,无论共享数据是否真会出现竞争,它都要进行加锁。

    随着硬件指令集的发展,多了一个选择:基于冲突检测的乐观并发政策,先进性操作,如果没有其他线程共享数据,则操作成功;如果共享数据有争用,产生冲突,那就采取其他措施(不断重试),这种乐观的并发政策的许多实现不用把线程挂起。乐观并发政策需要操作和冲突检测两个步骤具有原子性,需要底层硬件完成。

   x86中通过cmpxchg汇编指令来完成CAS操作。CAS(Compare-and-Swap 比较和交换)与平台相关,它有三个操作数,内存位置值(V),旧的预期值(A),新值(B)。CAS指令执行时,当V=A时,处理器用B的值跟新V的值,否则不执行。上述的过程是一个原子操作。JDK1.5引入的CAS,它在sun.misc.Unsafe类里面方法提供。里面调用了Native方法。

下面给一个JUC包下面的Atomic类的部分源代码,执行自增操作。用到CAS,里面用到了循环一直判断。里面没有进行加锁处理。但是也有逻辑漏洞,在111和222如果其他线程被执行,获得V(V运来是A),将他修改为B,后来又修改会A,则执行222代码的时候认为V没有改变过,这就是“ABA”问题。这个问题一般没有什么影响。

[java]  view plain  copy
  1. //该方法实现了i++的非阻塞的原子操作   
  2.    public final int getAndIncrement()    
  3.          for (;;)  //循环,使用CAS的经典方式,这是实现non-blocking方式的代价   
  4.             int current = get();//得到现在的值     111  
  5.             int next = current + 1;//通过计算得到要赋予的新值   
  6.             if (compareAndSet(current, next)) //关键点,调用CAS原子更新,  222  
  7.                  return current;   
  8.             
  9.         

    二.锁优化

   JDK1.6中高校并发是一个重要改进。里面的给出的各种锁都是为了线程间更高效的共享数据。优化的方法有下面几种。这里的锁优化主要是针对synchronized关键字来说,它产生的是一种重量级的锁定(重量级的锁定不是用CAS),会有互斥,效率较低。而在JDK1.6后,引入的自旋锁,轻量级锁,偏向锁对互斥同步进行了优化,它们三种锁默认都是开启的。

1.锁消除,锁粗化。锁消除是判断当堆上的数据不会被其他线程访问到时,该线程上的同步加锁就无需进行。

由于加锁和解锁的开销很大,如果不断的加锁和解锁操作都是对于同一个对象,虚拟机会把整个加锁同步的范围扩张到操作序列的外部,就是只加一次锁。

2.自旋锁:互斥同步对性能最大的影响是阻塞的实现,挂起线程和恢复线程都需要转入内核中完成。现将本该要阻塞的线程不去挂起,不放弃处理器的执行时间,而是在那做一个忙循环(自旋),看看持有锁的线程是否很快释放锁。自旋的次数(循环的次数)是有限度的,默认是10次,如果没有获得锁就采用传统的方式去挂起线程。

3.轻量级锁:在线程没有竞争的时候,采用CAS操作,避免使用互斥量的开销。这里涉及到对象头的概念。

4.偏向锁:它相对于轻量级锁,减少了锁重入的开销,对于第一个获得锁的线程,后面的执行如果该锁没有被其他线程获取,则该线程将不再进行同步(CAS操作)。

      轻量级锁和偏向锁都是在没有竞争的情况下出现,一旦出现竞争就会升级为重量级锁。

对于synchronized,锁的升级情况可能是 偏向锁—>轻量锁—>自适应自旋锁—>重量锁

 参考:

        《深入理解Java虚拟机》

         http://www.majin163.com/2014/03/17/synchronized2/  这一篇博文写了synchronized的原理,它的实现和性能怎么样可以看看这一篇。

转自:https://blog.csdn.net/u013080921/article/details/42676231

以上是关于JAVA锁中的CAS的主要内容,如果未能解决你的问题,请参考以下文章

带你快速了解Java锁中的公平锁与非公平锁

Java - 单例陷阱——双重检查锁中的指令重排问题

Mysql学习---MySQL悲观锁中的排它锁

如果锁对象是锁中的最后一条语句,那么覆盖它是不是不好?

获取synchronized锁中的阻塞队列中的线程是非公平的

Java——聊聊JUC中的CAS原理