为了开发者更方便的编写多线程程序,Java提供了一些原子操作类,在java.util.concurrent.atomic包下。

什么是原子操作?

操作:实现特定功能的1行或N行代码,或一个方法。

原子操作:多线程下,某个线程在执行该操作时,不允许被其他线程打断。

程序运行时,CPU在多个线程中快速的切换,每个线程在运行下一条指令前,都有可能失去CPU的执行权。

对于一个方法或代码块,如果不做任何处理,那么它肯定不是原子操作。

如何保证非原子操作的安全性?

  • synchronized
  • 加显式锁

但是这两种方式,开销都太大了,

synchronized:基于阻塞的锁机制

  • 被阻塞的线程优先级很高
  • 热点资源,大量锁竞争,消耗CPU
  • 产生死锁,以及其他线程安全问题。

对于一些简单的操作,使用synchronized或者显式锁开销太大了,为了解决这个问题,Java提供了原子操作类

原子操作类

java.util.concurrent.atomic包下提供了4种类型的操作类:

  • 原子更新基本类型
  • 原子更新数组
  • 原子更新引用
  • 原子更新属性

常用API

  • V get()
    获取值

  • void set(V v)
    赋值

  • void lazySet(V v)
    懒赋值,不能保证对其他线程的“可见性

  • V getAndSet(V v)
    返回旧值,并赋新值

  • boolean compareAndSet(V v1, V v2)
    比较并替换,返回是否替换成功

简单例子

public class AtomicBooleanDemo {AtomicInteger ai = new AtomicInteger(0);int i = 0;void add(){//休眠1ms 结果更明显SleepUtil.sleep(1);//原子操作System.out.println(ai.incrementAndGet());//非原子操作System.out.println(++i);}public static void main(String[] args) {AtomicBooleanDemo demo = new AtomicBooleanDemo();for (int i = 0; i < 1000; i++) {new Thread(()->{demo.add();}).start();}}
}

开启1000个线程去对i和ai加1,++i不是原子操作,输出结果最大值小于1000,incrementAndGet()是原子操作,输出结果最大值等于1000。

CAS

什么是CAS?

CAS:Compare and Swap,译为:比较并交换

CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。 如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值 。否则,处理器不做任何操作。

如果V和A相等,那么就用B来替换。

用Java代码描述如下:

public class CASDemo {int V;boolean compareAndSet(int A, int B) {if (V == A) {V = B;return true;}return false;}
}

这里的compareAndSet肯定是非原子操作。

CAS可以做到:在不加锁的情况下,确保“比较和替换”操作是原子的。

CAS操作是原子的,但不是锁。
它是利用现代处理器中都支持的原子指令来实现的,Java本身不能实现,需要调用本地方法,利用C语言/汇编来实现。

对于简单的“比较和替换”操作,就不要去使用锁,开销太大了,使用CAS性能更高。

存在的问题

  • ABA问题
    通过版本号解决

  • 开销问题

  • 只能保证一个共享变量的原子操作
    使用AtomicReference解决。

解决ABA问题

ABA问题:假设初始值为A,线程1首先将A改为B,线程2又将B改为A,线程3无法判断A是否被修改过。

Java提供了两个类来解决ABA问题:

  • AtomicMarkableReference
    记录是否被修改过。

  • AtomicStampedReference
    记录每次修改的版本号。

AtomicStampedReference除了比较期望值和原值是否相等外,还会判断版本号是否一致,只有都一致,才会进行修改。

AtomicStampedReference例子

public class AtomicStampedReferenceDemo {//构建AtomicStampedReference实例 并设置:初始值和初始版本号AtomicStampedReference<String> asr = new AtomicStampedReference("A", 0);public static void main(String[] args) {AtomicStampedReferenceDemo demo = new AtomicStampedReferenceDemo();//初始版本号int defaultStamp = demo.asr.getStamp();//初始值String defaultValue = demo.asr.getReference();//第一次修改 A > B 版本号 0 > 1 trueboolean oneChange = demo.asr.compareAndSet(defaultValue, "B", defaultStamp, defaultStamp+1);//第二次修改 B > A 版本号 1 > 2 trueboolean twoChange = demo.asr.compareAndSet("B", defaultValue, defaultStamp+1, defaultStamp+2);//第三次修改 A > B 版本号 0 > 1 falseboolean threeChange = demo.asr.compareAndSet(defaultValue, "B", defaultStamp, defaultStamp + 1);}
}

解决只能一个共享变量的问题

  • AtomicReference

AtomicReference使用和原子基本类型相似,区别是AtomicReference保存和比较的是对象引用的内存地址。

public class AtomicReferenceDemo {private static class Person{String name;int age;}public static void main(String[] args) {Person person = new Person();person.name = "admin";person.age = 18;AtomicReference<Person> ar = new AtomicReference<>();ar.set(person);Person newPerson = new Person();newPerson.name = "Lisa";newPerson.age = 23;//替换成功 ar内部指向newPersonar.compareAndSet(person, newPerson);Person arPerson = ar.get();System.out.println(arPerson == newPerson);//trueSystem.out.println(arPerson.name);//LisaSystem.out.println(person.name);//admin}
}

Java原子操作和CAS相关推荐

  1. Java原子操作Atomic

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/120854796 本文出自[赵彦军的博客] Java线程安全StampedLock ...

  2. JAVA并发编程: CAS和AQS

    说起JAVA并发编程,就不得不聊聊CAS(Compare And Swap)和AQS了(AbstractQueuedSynchronizer). CAS(Compare And Swap) 什么是CA ...

  3. Java 锁之 CAS

    什么是CAS(compare and swap)? CAS(Compare & Set,或是 Compare & Swap),即比较并交换,也是实现我们平时所说的自旋锁或乐观锁的核心操 ...

  4. 【面试篇】Java多线程并发-Java中的CAS机制算法

    Java中的CAS机制算法 a.CAS例子 再讲解CAS机制之前,先来看一道经典的并发执行1000次递增的问题: public class Test { public static int count ...

  5. 【高并发】java中的CAS,你需要知道的东西

    1.概述 转载:添加链接描述 从网站计数器实现中一步步引出CAS操作 介绍java中的CAS及CAS可能存在的问题 悲观锁和乐观锁的一些介绍及数据库乐观锁的一个常见示例 使用java中的原子操作实现网 ...

  6. JAVA 中的 CAS

    原文地址:https://www.xilidou.com/2018/02/01/java-cas/ CAS 是现代操作系统,解决并发问题的一个重要手段,最近在看 eureka 的源码的时候.遇到了很多 ...

  7. Java中的CAS操作

    Java中的CAS的含义 CAS即是Compare and Swap ,它是JDK提供的非阻塞原子性操作,它通过硬件保证了比较一更新操作的原子性.CAS 操作包含三个操作数-内存位置(V).预期原值( ...

  8. Java中的CAS以及AQS实现原理

    Java中的CAS实现原理 什么是CAS? 在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令. 它将内存位置的内容与给定值进行比较,只有在相同的情况下,将 ...

  9. Java原子操作类AtomicInteger应用场景

    参考文章:Java原子操作类AtomicInteger应用场景 感谢作者分享!

最新文章

  1. RxJava响应式编程学习笔记
  2. html列表穿插广告怎么实现,基于innerHTML中的script广告实现代码[广告全部放在一个js里面]...
  3. 海康开放平台音视频方案对比(rtsp、http-flv、hls、rtmp)
  4. Winform中使用OpenFileDialog选择文件打开并获取文件路径
  5. 最详细易懂的CRC-16校验原理(附源程序)
  6. 多帧点云数据拼接合并_自动驾驶:Lidar 3D传感器点云数据和2D图像数据的融合标注...
  7. 鸿蒙2.0beta报名,鸿蒙OS 2.0 Beta版系统在哪报名-报名方法介绍
  8. pushlet单播与多播
  9. [HNOI2008 Tree]
  10. mysql下删改增语句_MySQL增删改查
  11. Android Studio一直显示Building“project name”Gradle project info问题详解
  12. plc vb c语言编程,[转载]VB6.0在PLC和上位机通讯中的应用【工控老鬼分享】
  13. 决策树结果可视化中文乱码问题解决方案
  14. Excel文件编辑保护如何取消?
  15. React:Redux和Flux
  16. C++核心准则R.33: 表达函数会重置widget时,使用unique_ptr(widget)​作参数
  17. 乐视更新APP,图标显示欠122亿,反向营销?贾跃亭将回国造梦?
  18. iPhone 全系尺寸大全
  19. Unity2019,2020安装教程
  20. JS面试系列之节流

热门文章

  1. 英特尔中国研究院深度学习领域最新成果——“动态外科手术”算法
  2. 赣州服务器系统,赣州服务器费用
  3. STAHL触摸屏维修一体机显示屏ET-316-TX-TFT常见故障
  4. Qt编写安防视频监控系统47-基本设置
  5. 一篇编译内核的详细配置文章(超长-强烈推荐)
  6. 关于获取计算机唯一ID问题
  7. Wish卖家运营细节有什么?
  8. 武汉网络信息安全产业有望冲进三甲
  9. 贴片电阻0805 0603 1206分装是什么意思
  10. python风格变换图片_图片风格转换--深度学习介绍