CAS无锁机制深入领略

1.Java内存模子:JMM

  在内存模子傍边界说一个主内存,所有声明的实例变量都存在于主内存傍边,主内存的数据会共享给所有线程,每一个线程有一个块事情内存,事情内存傍边主内存数据的副本当更新数据时,会将事情内存中的数据同步到主内存傍边;

CAS无锁机制深入明确

2.什么是CAS 

  CAS:Compare and Swap,即较量互换;

  jdk1.5增加了并发包java.util.concurrent.*,其下面的类利用CAS算法实现了区别于synchronized同步锁的一种乐观锁。jdk1.5之前java语言是靠synchronized要害字担保同步的,这是一种独有锁,也是灰心锁;

3.CAS算法领略

  3.1 与锁对比,利用较量互换会使措施看起来越发巨大一些。但由于其非阻塞性,它对死锁问题天生免疫,而且,线程间的彼此影响也远远比基于锁的方法要小;更为重要的是,利用无锁的方法完全没有锁竞争带来的系统开销,也没有线程间频繁调治带来的开销;因此,它要比基于锁的方法拥有更优越的机能;

  3.2 无锁的长处:

    3.2.1 在高并发环境下,它比有锁的措施拥有更好的机能;

    3.2.2 它天生就是死锁免疫的;

  3.3 CAS算法的进程:

    它包括三个参数CAS(V,E,N):V暗示更新的变量,E暗示预期值,N暗示新值;    

    3.3.1 线程会见时,先会将主内存中的数据同步到线程的事情内存傍边
    3.3.2 假设线程A和线程B都有对数据举办变动,那么如果线程A先获取到执行权限
    3.3.3 线程A先会比拟事情内存傍边的数据和主内存傍边的数据是否一致,假如一致(V==E)则举办更新,纷歧致则刷新数据,从头轮回判定
    3.3.4 这时更新完毕后,线程B也要举办数据更新,主内存数据和事情内存数据做比拟,假如一致则举办更新,纷歧致则将主内存数据从头更新到事情内存,然后轮回再次比拟两个内存中的数据直到一致为止

CAS无锁机制深入明确

3.4 CAS操纵是抱着乐观的立场举办的,它老是认为本身可以乐成完成操纵;当多个线程同时利用CAS操纵一个变量时,只有一个会胜出,并乐成更新,其余均会失败;失败的线程不会被挂起,仅是被奉告失败,而且答允再次实验,虽然也答允失败的线程放弃操纵;基于这样的道理,CAS操纵纵然没有锁,也可以发明其他线程对当前线程的滋扰,并举办得当的处理惩罚;

  3.5 简朴的说,CAS需要你特别给出一个期望值,也就是你认为这个变量此刻应该是什么样子的;假如变量不是你想象的那样,那说明它已经被别人修悔改了;你就要从头读取,再次实验修改就好了;

  3.6 在硬件层面,大部门的现代处理惩罚器都已经支持原子性的CAS指令;在jdk1.5今后,虚拟机便可以利用这个指令来实现并发操纵和并发数据布局,而且,这种操纵在虚拟机中可以说是无处不在;

4.CAS缺点

  CAS存在一个很明明的问题,即ABA问题;

  问题:假如变量V初次读取的时候是A,而且在筹备赋值的时候查抄到它任然是A,那能说明它的值没有被其他线程修悔改了吗?

  假如在这段时间曾经被改成B,然后有改回A,那CAS操纵就会误任务它从来没有被修悔改。正对这种环境,java并发包提供了一个带有标志的原子应用类AtomicStampedRefernce,它可以通过变量值的版原来担保CAS的正确性;

5.原子类

  java中的原子类大抵可以分为四个类:

      原子更新根基范例;

      原子更新数组范例;

      原子更新引用范例;

      原子更新属性范例;

  这些原子类中都是用了无锁的观念,有的处所直接利用CAS操纵的线程安详的范例;

public class AtomicIntegerTest implements Runnable { private static Integer count=1; private static AtomicInteger atomicInteger=new AtomicInteger(); @Override public void run() { while (true){ int count=getCountAtomic(); System.out.println(count); if (count>=150){ break; } } } public synchronized Integer getCount(){ try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } return count++; } public Integer getCountAtomic(){ try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } return atomicInteger.incrementAndGet(); } public static void main(String[] args){ AtomicIntegerTest test = new AtomicIntegerTest(); Thread thread1 = new Thread(test); Thread thread2 = new Thread(test); thread1.start(); thread2.start(); } }

Linux公社的RSS地点https://www.linuxidc.com/rssFeed.aspx

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsdjfx.html