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

在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多线程(5):CAS的更多相关文章

  1. Java多线程:CAS与java.util.concurrent.atomic

    锁的几种概念 悲观锁 总是假设最坏的情况,每次获取数据都认为别人会修改,所以拿数据时会上锁,一直到释放锁不允许其他线程修改数据.Java中如synchronized和reentrantLock就是这种 ...

  2. Java多线程系列——原子类的实现(CAS算法)

    1.什么是CAS? CAS:Compare and Swap,即比较再交换. jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronou ...

  3. java 多线程12 : 无锁 实现CAS原子性操作----原子类

    由于java 多线程11:volatile关键字该文讲道可以使用不带锁的情况也就是无锁使变量变成可见,这里就理解下如何在无锁的情况对线程变量进行CAS原子性及可见性操作 我们知道,在并发的环境下,要实 ...

  4. Java多线程并发06——CAS与AQS

    在进行更近一步的了解Java锁的知识之前,我们需要先了解与锁有关的两个概念 CAS 与 AQS.关注我的公众号「Java面典」了解更多 Java 相关知识点. CAS(Compare And Swap ...

  5. Java多线程--CAS

    在Java多线程并发的情况下同时对一个变量进行操作会出现线程安全的问题,假如我们现在使用20个线程对一个变量不停累加1,代码如下: 1 public class ThreadDemo implemen ...

  6. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  7. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  8. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  9. java多线程系类:JUC线程池:03之线程池原理(二)(转)

    概要 在前面一章"Java多线程系列--"JUC线程池"02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包 ...

  10. java多线程系类:JUC原子类:03之AtomicLongArray原子类

    概要 AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray这3个数组类型的原子类的原理和用法相似.本章以AtomicLongArray对数 ...

随机推荐

  1. 自己做一个RTOS

    什么是操作系统?其实就是一个程序, 这个程序可以控制计算机的所有资源,对资源进行分配,包括CPU时间,内存,IO端口等,按一定规则分配给所需要的进程(进程?也就是一个程序,可以单独执行),并且自动控制 ...

  2. java单线程100%利用率

    容器内就获取个cpu利用率,怎么就占用单核100%了呢 背景:这个是在centos7 + lxcfs 和jdk11 的环境上复现的 目前这个bug已经合入到了开源社区, 链接为 https://git ...

  3. 【java】学习路径17-StringBuffer、StringBuilder的使用与区别

    本文讲解StringBuffer和StringBuilder的使用与区别. 1-- String String类型我们已经很熟悉了,String一旦被赋值,其在堆中的数据便无法修改. 平时我们的&qu ...

  4. C# Hashtable VS. Dictionary 性能对比

    Hashtable VS Dictionary 因为Hashtable的Key和Value都是object类型,所以在使用值类型的时候,必然会出现装箱和拆箱的操作,因此性能肯定是不如Dictionar ...

  5. Can't pickle local object '_createenviron.<locals>.encodekey'报错解决

    关于selenium传参报错问题,用下面是报错信息: Traceback (most recent call last): File "D:/code/read_book/main.py&q ...

  6. KingbaseES 的行列转换

    目录 背景 行转列 数据准备 分组聚合函数+CASE 根据压缩数据的格式,横向展开数据列选取不同方式 crosstab函数 PIVOT 操作符 PIVOT 操作符的限制 工具 ksql 的元命令 \c ...

  7. 使用 MAUI 在 Windows 和 Linux 上绘制 PPT 的图表

    我在做一个图表工具软件,这个软件使用 MAUI 开发.我的需求是图表的内容需要和 PPT 的图表对接,需要用到 OpenXML 解析 PPT 内容,读取到 PPT 图表元素的内容,接着使用 MAUI ...

  8. torch.meshgrid

    1:https://blog.csdn.net/weixin_39504171/article/details/106356977 2: https://pytorch.org/docs/stable ...

  9. Scanner中nextInt()和nextline()读取字符串的问题

    Scanner中nextInt()和nextline()读取字符串的问题 import java.util.Scanner; public class Main { public static voi ...

  10. 基于HBuilderX+UniApp+ThorUI的手机端前端开发处理

    现在的很多程序应用,基本上都是需要多端覆盖,因此基于一个Web API的后端接口,来构建多端应用,如微信.H5.APP.WInForm.BS的Web管理端等都是常见的应用.本篇随笔概括性的介绍基于HB ...