zoukankan      html  css  js  c++  java
  • Java多线程并发中 CAS 的使用与理解

    一、CAS (Compare And Swap):

      CAS(Compare And Swap),即比较并交换 CAS(V,E,N)。是解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数——要更新的变量(V)、预期原值(E)和新值(N)核心算法是如果V 值等于E 值,则将V 的值设为N 。若V 值和E 不同,则说明已经有其他线程做了更新,则当前线程不做更新,直到V、E两个值相等,才更新V的值。
      1、代码演示:

    /*
    * 原子变量类:
    *      AtomicBoolean
    *      AtomicInteger
    *      AtomicLong
    *      AtomicReference
    *
    * 原子数组类:
    *      AtomicLongArray
    *      AtomicReferenceArray
    *
    * 原子方式更新对象中的字段类:
    *      AtomicIntegerFieldUpdate
    *      AtomicReferenceFieldUpdate
    *
    * 高并发汇总类:
    *      LongAdder
    *      LongAccumulator
    *      DoubleAdder
    *      DoubleAccumulator
    *
    */
    public class CASTest {
    
        public static void main(String[] args) throws InterruptedException {
            AtomicInteger counter = new AtomicInteger(0);
            CountDownLatch c = new CountDownLatch(10000);
    
            for(int i = 0; i < 50; i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.print( counter.incrementAndGet() + " ");            
                        c.countDown();
                    }
                }).start();
            }
            c.await();
            System.out.println("AtomicInteger :" +  counter.get());
        }
    }

    二、CAS 中 ABA 问题:

      ABA 问题是指假设当前值为 A ,如果另一个线程先将 A 修改成 B , 再修改回成 A ,当前线程的 CAS 操作无法分辨当前值发生过变化。ABA 是不是一个问题与程序的逻辑有关,一般不是问题。而如果确实有问题,解决方法是使用 AtomicStampedReference ,在修改值的同时附加一个时间戳,只有值和时间戳都相同才进行修改。

      1、代码演示:

    public class ABATest {
    public static void main(String[] args) throws InterruptedException { CASABATest(); atomicStampedReferenceTest(); } public static void atomicStampedReferenceTest(){ AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(0, 0); // 第一个参数:引用对象的初始值,第二个参数:这个对象的初始标记 new Thread(new Runnable() { @Override public void run() {
             // compareAndSet(eR,nR,eS,nS) eR:引用对象的期望值,nR:引用对象的新值,eS:引用对象期望标记,nS:引用对象的新标记,当 eR、eS和当前线程的值相等才会修改eR、eS的值为nR、nS System.out.println(Thread.currentThread().getName()
    + ", " + atomicStampedReference.compareAndSet(0, 1, 0, 1) + ", atomicStampedReference value:" + atomicStampedReference.getReference()); } },"Thread A").start(); new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + ", " + atomicStampedReference.compareAndSet(1, 0, 1, 2) + ", atomicStampedReference value:" + atomicStampedReference.getReference()); } },"Thread B").start(); new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + ", " + atomicStampedReference.compareAndSet(0, 1, 0, 1) + ", atomicStampedReference value:" + atomicStampedReference.getReference()); } },"Thread C").start(); } /** * 演示CAS 更新的ABA 问题 * */ public static void CASABATest() throws InterruptedException { AtomicInteger integer = new AtomicInteger(0); new Thread(new Runnable() { @Override public void run() {
              //compareAndSet(e,u) e:期望值,u:新值,如果e的值在当前线程中和integer的值一致,就把e的值修改成u的值 System.out.println(Thread.currentThread().getName()
    + ", " + integer.compareAndSet(0, 1) + ", AtomicInteger value:" + integer); //true } },"Thread A").start(); new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + ", " + integer.compareAndSet(1 , 0) + ", AtomicInteger value:" + integer); //true } },"Thread B").start(); new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + ", " + integer.compareAndSet(0 , 1) + ", AtomicInteger value:" + integer); //true } },"Thread C").start(); } }

    三、CAS 与 Synchronized 的对比:
      1.synchronized 是悲观的,它假设更新都是可能冲突的,所以要先获取锁,得到锁才更新,它是阻塞式算法,得不到锁就进入锁池等待。
      CAS 是乐观的,它假设冲突比较少,但使用CAS 更新,进行冲突检测,如果确实冲突就继续尝试直到成功,它是非阻塞式算法,有更新冲突就重试。

  • 相关阅读:
    [原创]启发式测试策略模型
    [原创]SSH框架介绍
    [原创]Sniffer工具培训
    [原创]浅谈Devops理念
    [原创接口测试技术介绍
    一个让我看了之后,痛哭不止的舞蹈!寻找有同感的人!
    多一点宽容,少一点抱怨;多一点付出,少一点指责。
    笼屉与夹肉馍(的制作方法) 之于 三层与MVC
    找工作、跳槽之旅——前言
    【自然框架.视频】基础设置(一)如何下载自然框架
  • 原文地址:https://www.cnblogs.com/haiyangwu/p/10437208.html
Copyright © 2011-2022 走看看