首页 > 编程语言 >Java多线程(5):CAS

Java多线程(5):CAS

时间:2022-10-28 06:55:05浏览次数:56  
标签:Java CAS int volatile 多线程 public

 

您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~

 

 

在JDK1.5之前,Java的多线程都是靠synchronized来保证同步的,这会引起很多性能问题,例如死锁。但随着Java的不断完善,JNI(Java Native Interface)使得Java能越过JVM直接调用本地方法,例如CAS。

CAS是Compare And Swap(比较与交换)的缩写,它用于实现多线程同步的原子指令,允许算法执行读-修改-写操作,而无需担心其他线程同时修改变量。说人话,意思就是它的操作过程足够细微,以至于线程都奈何不了它。

所谓原子指令就是指不会被线程调度机制打断的操作指令,这种操作一旦开始,就一直运行到结束,中间不会有任何线程切换,即要么全部完成,要么全部中断。换一种说法,就是CAS可以保证Java运算实现我们想要的操作而无需担心会受到多线程的影响。

某种程度上,CAS可以用来取代synchronized的强制同步,提升性能。其实整个java.util.concurrent包都是建立在CAS之上的,尤其是Java中大多数锁的实现基类AbstractQueuedSynchronizer,更是以CAS为基础,提供了一系列的独占锁、共享锁、可重入锁、自旋锁、读写锁等多线程控制手段(这在后面会说)。就像图中那样:

 

 

 

Java对CAS的实现都在java.util.concurrent.atomic包下(java.util.concurrent也简称JUC,这是个简称。所以如果有面试官说想让你谈谈JUC相关的问题,不要一脸懵,否则会被立即淘汰)。以AtomicInteger为例,从源码可以看出CAS操作都是通过sun包下Unsafe类实现,而Unsafe类中的方法都是native方法,由本地实现,和操作系统、CPU都有关系。CAS有一个比较通用的实现模式:

1、首先声明(共享)变量为volatile

2、然后使用CAS的原子条件来更新

3、同时配合volatile的可见性来实现线程之间的同步

前面讲过,不用深究volatile关键字的用途,因为随着机器配置的豪华,其实这个关键字已经没啥用了,而且也可以看到,在CAS里面也有大量出现,JDK已经替你用好了,自己如果不太熟悉就不要用了。CAS相关类结构图是:

 

 

 

还是老规矩,用代码来举例:

/**
 * 仅用AtomicInteger实现CAS
 *
 * @author 湘王
 */
public class AtomicIntegerTester1 {
    // 使用AtomicInteger实现CAS,有没有volatile都不影响
    public static volatile AtomicInteger atomicInteger = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        for (int i = 0; i < 20; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    atomicInteger.getAndIncrement();
                }
            };
            executor.submit(runnable);
        }

        // 为了观察效果休眠,但实际生产环境中肯定不允许
        Thread.sleep(100);
        executor.shutdown();
        System.out.println(atomicInteger.get());
    }
}



/**
 * 用AtomicIntegerFieldUpdater实现CAS
 *
 * @author 湘王
 */
public class AtomicIntegerTester2 {
    /*
     * 使用AtomicIntegerFieldUpdater实现CAS,相关计算字段必须用volatile修饰,不然抛异常
     * Caused by: java.lang.IllegalArgumentException: Must be volatile type
     *
     */
    public volatile int count = 0;
    public static final AtomicIntegerFieldUpdater<AtomicIntegerTester2> lockUpdate = AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerTester2.class, "count");

    public int increase(int inc) {
        return lockUpdate.addAndGet(this, inc);
    }

    public int get() {
        return lockUpdate.get(this);
    }

    public static void main(String[] args) throws InterruptedException {
        AtomicIntegerTester2 tester = new AtomicIntegerTester2();
        ExecutorService executor = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 20; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    tester.increase(1);
                }
            };
            executor.submit(runnable);
        }
        // 为了观察效果休眠,但实际生产环境中肯定不允许
        Thread.sleep(100);
        executor.shutdown();
        System.out.println(tester.get());
    }
}

 

 

 

CAS的内容并不多,可以看看它的源码,还是比较有意思的。

 


 

 

 

感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~

 

标签:Java,CAS,int,volatile,多线程,public
From: https://www.cnblogs.com/xiangwang1111/p/16834406.html

相关文章

  • 基于springboot+vue物资管理系统java物资统计系统(源码调试+讲解+文档)
    ......
  • JavaScript 手写深拷贝
    深拷贝深拷贝就是要拷贝的对象内的所有引用类型的属性进行完整的拷贝;也就是说拷贝出来的对象和原对象之间没有任何数据是共享的,所有的东西都是自己独占的一份;三步实现深......
  • java中类的关系的总结
    类和类之间存在多种关系,而这种关系在我们的代码中司空见惯,有时多种类关系很难区分(由于水平有限,没有画出类的关系图,关系图可以参考参考链接)继承关系继承是指一个子类......
  • JAVA-二维数组元素打乱
    packagecom.itheima;importjava.util.Random;publicclassshuzu07{publicstaticvoidmain(String[]args){int[][]arr={{1,2,3},{4,5,6},{7,......
  • JAVA-二维数组遍历
    改进代码改进代码最终遍历代码packagecom.itheima;publicclassshuzu06{publicstaticvoidmain(String[]args){int[][]arr={{1,2,3},{4,5,......
  • Java序列化和反序列化
    java序列化:java对象转换为字节序列过程,java反序列化把字节序列恢复为java对象的过程Serializable实现序列化Java中,只要一个类实现了java.io.Serializable接口,可以序列化......
  • JAVA常见基础知识点
    JAVA常见基础知识点一、注释Java中有三种注释,分别是单行注释、多行注释、文档注释。单行注释:注释某一行代码。使用//多行注释:注释某一段代码。使用/*...*/文档注释......
  • JAVA-二维数组 和元素访问
    二维数组的定义静态初始化动态初始化packagecom.itheima;publicclassshuzu04{publicstaticvoidmain(String[]args){int[][]arr={{7,9,10......
  • 【Java】来回顾下JWT知识点,了解一下什么是JWT?
    (回顾下JWT知识点)1.什么是JWT在介绍JWT之前,我们先来回顾一下利用token进行用户身份验证的流程:1.客户端使用用户名和密码请求登录。2.服务端收到请求,验证用户名和密码......
  • Java开发笔记之EasyExcel实现自定义合并策略
    0x00概述本文转载,原文原本是想学习使用Apache的POI的,但是无意中看到Alibaba的开源工具EastExcel,据说比POI更加快速高效,关键是使用起来也简单。官网地址为:https://aliba......