zoukankan      html  css  js  c++  java
  • 线程基础知识02-CAS (CompareAndSwap)

    1.基本概念  

      原子性是不可中断的最小操作;在Java中,一般通过加锁或者自旋CAS方式来确保原子操作;

      而CAS(compareAnd swap)作为Java中常用的保证原子性的手段,JDK1.5之后就提供了相关的操作类,java.util.concurrent.atomic包中的工具类;

      CAS概念:CAS操作需要两个值,旧值(预期的操作之前的值)和新值,先将旧值进行比较,如果旧值没有发生变化,则进行操作,如果旧值变化则不进行任何操作

     2.常用来解释CAS的一个案例:

    public class CASTest {
        private int i = 0;
        private AtomicInteger ai = new AtomicInteger();
        private static final Integer NUM = 10;
        private static CountDownLatch latch = new CountDownLatch(NUM);
    
        public static void main(String[] args) throws InterruptedException {
            final CASTest t = new CASTest();
            for(int i =0 ; i < NUM ; i++){
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for(int j = 0 ; j < 100 ; j++){
                            t.count();
    //                        t.safeCount();
                        }
                        latch.countDown();
                    }
                });
                thread.start();
            }
            latch.await();
            System.out.println("======= over ======="+t.i);
        }
    
        public  void count(){
            i ++ ;
        }
        
        public void safeCount(){
            for(;;){
                int i = ai.get();
                boolean b = ai.compareAndSet(i, i++);
                if( b ){
                    break ;
                }
            }
    
        }
    }

    理想的结果是1000,但是非CAS的结果总是会有差异,而safeCount 采用的是CAS的方式进行原子操作;

    3.CAS 操作存在的问题和解决方案

    1.ABA问题

      问题描述:首先,假设一个变量经过A=>B=>A的变化过程,一个线程进行,获取到操作前的值为A,按照上面的概念这个线程获取到的旧值A,和这个变量进行变化后的现在的新值A是一样的。如果进行CAS自旋操作无疑是有问题的。

      解决方案:JDK中atomic包中提供了,AtomicStampedReference 类,提供了更完善的方法。通过增加标志,来对旧值进行判断。

     2.循环时间长开销大

      问题描述:当一个线程修改的值,被其他线程再次修改后,自旋旧值比对长时间无法获取成功,导致资源的浪费;

           解决方案:JVM中提供了puse指令可以解决这种问题;

    3.只能保证一个变量的原子操作

      问题描述:如题

           解决方案:通过将多个变量封装成一个对象,通过atomic包中的AtomicReference类来进行解决;

    参考图书《java并发编程艺术》(ps:这个随笔就是看书笔记)

    最后,

  • 相关阅读:
    Python数据分析(一)pandas数据切片
    回归分析
    C# + ArcEngine 常用方法(不定时更新)
    安卓11配置谷歌FCM推送报错
    VUE开发之异常篇
    C#编程之“串口通讯多次接收”
    关于swift使用CocoaPods倒入三方库的framework后父类倒入子类无法继承的问题
    warning: directory not found for option“XXXXXX” 解决方案
    关于获取tableView中cell数据的处理
    怎么处理使用UINavigation(导航控制器时) UIScrollView及其子类UITableView、UICollectionView可能出现的向下偏移64Px或者顶部对齐等问题
  • 原文地址:https://www.cnblogs.com/perferect/p/12761558.html
Copyright © 2011-2022 走看看