• JUC并发编程——CAS与原子引用(基于狂神说的学习笔记)


    CAS

    CAS与原子引用涉及到JVM以及更底层的一些知识,笔者会在JVM篇中写的更细致一点

    什么是CAS

    CAS 是Java设置的CPU的并发原语

    Java是无法直接操作内存的

    但Java可以调用C++

    而C++可以操作内存

    Java可以通过native类调用C++来操作内存

    CAS = Compare And Set 比较并交换

    CAS是:比较当前内存中的值和主内存中的值,如果这个值是期望的,那么则执行操作,如果不是就一直循环比较(自循环)

    缺点:

    1、自循环会耗时

    2、一次性职能保证一个共享变量的原子性

    3、会存在ABA问题

    /**
     * Atomically sets the value to newValue
     * if the current value code == expectedValue,
     * with memory effects as specified by VarHandle#compareAndSet.
     *
     * @param expectedValue the expected value
     * @param newValue the new value
     * @return true if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expectedValue, int newValue) {
        return U.compareAndSetInt(this, VALUE, expectedValue, newValue);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    package CAS;
    
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class casDemo {
    
        // CAS 是CPU的并发原语
        // compareAndSet:比较并交换
        public static void main(String[] args) {
            AtomicInteger atomicInteger = new AtomicInteger(2020);
            // public final boolean compareAndSet(int expectedValue, int newValue)
            // expectedValue:期望值    newValue:更新值
            // 比较,如果期望值达到了,则变为更新值,否则就不跟新
            atomicInteger.compareAndSet(2020,2023);
            System.out.println(atomicInteger.get());
    
            System.out.println(atomicInteger.compareAndSet(2020, 2023));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    原子引用

    带版本号的原子操作 解决ABA问题! 与乐观锁很相似!

    package CAS;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicStampedReference;
    
    public class casDemo02 {
    // AtomicStampedReference 注意,如果泛型时一个包装类,注意对象的引用问题
        public static void main(String[] args) {
            AtomicStampedReference<Integer> atomicInteger = new AtomicStampedReference<>(1,1);
    
            new Thread(()->{
                // 获得目前的版本号(时间戳)
                int stamp = atomicInteger.getStamp();
                System.out.println("A1=>"+stamp);
    
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
    
                System.out.println(atomicInteger.compareAndSet(1, 2, atomicInteger.getStamp(), atomicInteger.getStamp() + 1));
                System.out.println("A2=>"+atomicInteger.getStamp());
                System.out.println(atomicInteger.compareAndSet(2, 1, atomicInteger.getStamp(), atomicInteger.getStamp() + 1));
                System.out.println("A3=>"+atomicInteger.getStamp());
    
            },"A").start();
    
            new Thread(()->{
                // 获得目前的版本号(时间戳)
                int stamp = atomicInteger.getStamp();
                System.out.println("B1=>"+stamp);
    
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
    
                System.out.println(atomicInteger.compareAndSet(1, 6, stamp, stamp + 1));
                System.out.println("B1=>"+atomicInteger.getStamp());
            },"B").start();
    
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    注意:

    Integer使用了对象缓存机制,默认范围是-128~127,推荐使用静态工厂方法valueOf获取对象实例,而不是new,因为valuOf使用缓存,而new一定会创建新的对象分配新的内存空间;

    在示例中,我们一开始使用的expectedRefrence 和 newReference 都是大于127的且使用new获取对象,因此,内存中创造了新的对象分配新的空间,所以使用cas时一直为false

  • 相关阅读:
    Pytorch 梯度计算,叶子节点,requires_grad,detach
    人工智能方向专利和论文相关
    Mybatis引入外部properties文件
    【JAVA】抽象类和接口类
    js基础笔记学习67-对象得属性2
    [附源码]Java计算机毕业设计SSM服装商城平台
    ORM框架,反射,泛型,注解,CRUD实现
    mysql5.7.21 安装与使用
    git bash指北
    【M365运维】给从本地同步到O365的DL添加 Send As权限
  • 原文地址:https://blog.csdn.net/whale_cat/article/details/133932955