java 原子类能做什么_死磕 java原子类之终结篇(面试题)

概览

原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程上下文切换。

原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分,将整个操作视作一个整体是原子性的核心特征。

在java中提供了很多原子类,笔者在此主要把这些原子类分成四大类。

9a354587719ba2e60da0fb6b899c19ef.png

原子更新基本类型或引用类型

如果是基本类型,则替换其值,如果是引用,则替换其引用地址,这些类主要有:

(1)AtomicBoolean

原子更新布尔类型,内部使用int类型的value存储1和0表示true和false,底层也是对int类型的原子操作。

(2)AtomicInteger

原子更新int类型。

(3)AtomicLong

原子更新long类型。

(4)AtomicReference

原子更新引用类型,通过泛型指定要操作的类。

(5)AtomicMarkableReference

原子更新引用类型,内部使用Pair承载引用对象及是否被更新过的标记,避免了ABA问题。

(6)AtomicStampedReference

原子更新引用类型,内部使用Pair承载引用对象及更新的邮戳,避免了ABA问题。

这几个类的操作基本类似,底层都是调用Unsafe的compareAndSwapXxx()来实现,基本用法如下:

private static void testAtomicReference() {

AtomicInteger atomicInteger = new AtomicInteger(1);

atomicInteger.incrementAndGet();

atomicInteger.getAndIncrement();

atomicInteger.compareAndSet(3, 666);

System.out.println(atomicInteger.get());

AtomicStampedReference atomicStampedReference = new AtomicStampedReference<>(1, 1);

atomicStampedReference.compareAndSet(1, 2, 1, 3);

atomicStampedReference.compareAndSet(2, 666, 3, 5);

System.out.println(atomicStampedReference.getReference());

System.out.println(atomicStampedReference.getStamp());

}

原子更新数组中的元素

原子更新数组中的元素,可以更新数组中指定索引位置的元素,这些类主要有:

(1)AtomicIntegerArray

原子更新int数组中的元素。

(2)AtomicLongArray

原子更新long数组中的元素。

(3)AtomicReferenceArray

原子更新Object数组中的元素。

这几个类的操作基本类似,更新元素时都要指定在数组中的索引位置,基本用法如下:

private static void testAtomicReferenceArray() {

AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(10);

atomicIntegerArray.getAndIncrement(0);

atomicIntegerArray.getAndAdd(1, 666);

atomicIntegerArray.incrementAndGet(2);

atomicIntegerArray.addAndGet(3, 666);

atomicIntegerArray.compareAndSet(4, 0, 666);

System.out.println(atomicIntegerArray.get(0));

System.out.println(atomicIntegerArray.get(1));

System.out.println(atomicIntegerArray.get(2));

System.out.println(atomicIntegerArray.get(3));

System.out.println(atomicIntegerArray.get(4));

System.out.println(atomicIntegerArray.get(5));

}

原子更新对象中的字段

原子更新对象中的字段,可以更新对象中指定字段名称的字段,这些类主要有:

(1)AtomicIntegerFieldUpdater

原子更新对象中的int类型字段。

(2)AtomicLongFieldUpdater

原子更新对象中的long类型字段。

(3)AtomicReferenceFieldUpdater

原子更新对象中的引用类型字段。

这几个类的操作基本类似,都需要传入要更新的字段名称,基本用法如下:

private static void testAtomicReferenceField() {

AtomicReferenceFieldUpdater updateName = AtomicReferenceFieldUpdater.newUpdater(User.class, String.class,"name");

AtomicIntegerFieldUpdater updateAge = AtomicIntegerFieldUpdater.newUpdater(User.class, "age");

User user = new User("tong ge", 21);

updateName.compareAndSet(user, "tong ge", "read source code");

updateAge.compareAndSet(user, 21, 25);

updateAge.incrementAndGet(user);

System.out.println(user);

}

private static class User {

volatile String name;

volatile int age;

public User(String name, int age) {

this.name = name;

this.age = age;

}

@Override

public String toString() {

return "name: " + name + ", age: " + age;

}

}

高性能原子类

高性能原子类,是java8中增加的原子类,它们使用分段的思想,把不同的线程hash到不同的段上去更新,最后再把这些段的值相加得到最终的值,这些类主要有:

(1)Striped64

下面四个类的父类。

(2)LongAccumulator

long类型的聚合器,需要传入一个long类型的二元操作,可以用来计算各种聚合操作,包括加乘等。

(3)LongAdder

long类型的累加器,LongAccumulator的特例,只能用来计算加法,且从0开始计算。

(4)DoubleAccumulator

double类型的聚合器,需要传入一个double类型的二元操作,可以用来计算各种聚合操作,包括加乘等。

(5)DoubleAdder

double类型的累加器,DoubleAccumulator的特例,只能用来计算加法,且从0开始计算。

这几个类的操作基本类似,其中DoubleAccumulator和DoubleAdder底层其实也是用long来实现的,基本用法如下:

private static void testNewAtomic() {

LongAdder longAdder = new LongAdder();

longAdder.increment();

longAdder.add(666);

System.out.println(longAdder.sum());

LongAccumulator longAccumulator = new LongAccumulator((left, right)->left + right * 2, 666);

longAccumulator.accumulate(1);

longAccumulator.accumulate(3);

longAccumulator.accumulate(-4);

System.out.println(longAccumulator.get());

}

问题

关于原子类的问题,笔者整理了大概有以下这些:

(1)Unsafe是什么?

(3)Unsafe为什么是不安全的?

(4)Unsafe的实例怎么获取?

(5)Unsafe的CAS操作?

(6)Unsafe的阻塞/唤醒操作?

(7)Unsafe实例化一个类?

(8)实例化类的六种方式?

(9)原子操作是什么?

(10)原子操作与数据库ACID中A的关系?

(11)AtomicInteger怎么实现原子操作的?

(12)AtomicInteger主要解决了什么问题?

(13)AtomicInteger有哪些缺点?

(14)ABA是什么?

(15)ABA的危害?

(16)ABA的解决方法?

(17)AtomicStampedReference是怎么解决ABA的?

(18)实际工作中遇到过ABA问题吗?

(19)CPU的缓存架构是怎样的?

(20)CPU的缓存行是什么?

(21)内存屏障又是什么?

(22)伪共享是什么原因导致的?

(23)怎么避免伪共享?

(24)消除伪共享在java中的应用?

(25)LongAdder的实现方式?

(26)LongAdder是怎么消除伪共享的?

(27)LongAdder与AtomicLong的性能对比?

(28)LongAdder中的cells数组是无限扩容的吗?

关于原子类的问题差不多就这么多,都能回答上来吗?点击下面的链接可以直接到相应的章节查看:

彩蛋

原子类系列源码分析到此就结束了,虽然分析的类比较少,但是牵涉的内容非常多,特别是操作系统底层的知识,比如CPU指令、CPU缓存架构、内存屏障等。

下一章,我们将进入“同步系列”,同步最常见的就是各种锁了,这里会着重分析java中的各种锁、各种同步器以及分布式锁相关的内容。

欢迎关注我的公众号“彤哥读源码”,查看更多源码系列文章, 与彤哥一起畅游源码的海洋。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/563799.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java对docker_如何在docker中运行java程序

吃鸡游戏创建一个redis docker容器首先&#xff0c;我们先为redis创建一个DockerfileFROM ubuntu:12.10RUN apt-get updateRUN apt-get -y install redis-serverEXPOSE 6379ENTRYPOINT ["/usr/bin/redis-server"]现在你需要通过Dockerfile创建一个镜像&#xff0c;将…

java canvas 画图片_canvas画布——画八卦图

浏览器支持Internet Explorer 9、Firefox、Opera、Chrome 以及 Safari 支持 arc() 方法。注释&#xff1a;Internet Explorer 8 或更早的浏览器不支持 元素。定义和用法arc() 方法创建弧/曲线(用于创建圆或部分圆)。提示&#xff1a;如需通过 arc() 来创建圆&#xff0c;请把起…

java多线程编程—高级主题_Java day20 高级编程【第一章】Java多线程编程

【第一章】Java多线程编程一.进程与线程多个时间段会有多个程序依次执行&#xff0c;但是同一时间点只有一个进程执行线程是在进程基础之上划分的更小的程序单元 &#xff0c;线程是在进程基础上创建并且使用的&#xff0c;所以线程依赖于进程的支持&#xff0c;但是来讲&#…

java object数组转实体类_详解Java中String JSONObject JSONArray List实体类转换

JSON使用阿里的fastJson为依赖包gradle依赖管理如下&#xff1a;compile group: "com.alibaba", name: "fastjson", version:"1.2.41"1、String转JSONObject前言&#xff1a;String 是JSONObject格式的字符串eg:JSONObject jSONObject JSONObje…

e x泰勒 java_maven project

最近没事了玩一下maven&#xff0c;使用maven管理工程中的依赖包非常的方便。建立maven web工程的时候开始不知道怎么用tomcat来调试&#xff0c;总是使用mave的tomcat插件发布了后来调试&#xff0c;觉得非常的麻烦&#xff0c;网上找了点材料&#xff0c;看看maven web工程不…

java定义说话方法_类定义的基本形式_Java语言程

类定义的基本形式_Java语言程4&#xff0e;2&#xff0e;1 类定义的基本形式前面一节我们已经了解了类和对象的概念&#xff0c;然而在实际编程过程中&#xff0c;该如何定义一个类以及类中的对象呢&#xff1f;在Java语言中&#xff0c;用户自己可以定义一个类&#xff0c;作…

java创建线程几种_java中创建线程有几种方式

详细内容线程的创建方式1、继承Thread类实现多线程2、覆写Runnable()接口实现多线程&#xff0c;而后同样覆写run()。推荐此方式3、使用Callable和Future创建线程相关视频教程推荐&#xff1a;java学习视频实例如下&#xff1a;1、继承Thread类实现多线程/** 继承Thread类创建线…

php自定义中文分词方法,php实现的中文分词类完整实例

本文实例讲述了php实现的中文分词类。分享给大家供大家参考&#xff0c;具体如下&#xff1a;该中文分词类源码使用http://tools.ddpool.cn/code/jb51_php_format进行了格式化处理&#xff0c;便于阅读。具体代码如下&#xff1a;class Segmentation {var $options array(lowe…

手机电脑自适应导航源码php,自适应各终端懒人网址导航源码 v2.0

自适应各终端懒人网址导航源码。V2.0版本是在原1.8版本的基础上修复和增加了些功能。推荐直接使用新版本&#xff0c;舍弃旧版本&#xff0c;后期会继续不定期更新。测试环境&#xff1a;宝塔Nginx -Tengine2.2.3的php5.5mysql先导入数据库文件db/db.sql再修改config.php数据库…

php如何生成本地文档,php如何生成word文件

php生成word文件的方法&#xff1a;需求&#xff1a;甲方爸爸说“我有一个word文件&#xff0c;里面是关于用户信息的表格&#xff0c;你帮我把系统里面所有用户数据都按照这个文件导出来给我“&#xff1b;我当时就不乐意了&#xff0c;啪的一拍桌子站起来&#xff0c;愤愤的回…

php 显示状态,php-fpm status状态配置显示

系统为ubuntu,在usr/etc/sites-enabled/中编辑nginx配置文件server_name demo.com;location ~^/status$ {#auth_basic "status page";#fastcgi_index index.php;fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;include fastcgi_params;fastcgi_pass unix:/var/…

matlab 动态目录调用程序集,C#中如何动态添加程序集查找目录

C#中如何动态添加程序集查找目录情况如下&#xff1a;现有三个程序集Main.exe, One.dll, Two.dll。其中One.dll引用了Two.dll&#xff0c; 并且One.dll与Two.dll部署在一起, 而Main.exe单独部署。在One.dll中有using Two;namespace One{public SomeType{public void DoSomethin…

matlab 红黑强度图片,matlab图形锐化程序

满意答案gveial5852013.10.31采纳率&#xff1a;50% 等级&#xff1a;12已帮助&#xff1a;11498人help imreadhelp fspecial imfilt帮助稳定中有较多的示例fspecial 函数功能&#xff1a;产生预定义滤波器格式&#xff1a;Hfspecial(type)Hfspecial(gaussian,n,sigma) 高斯…

php基础学哪些,榆林学习php需要哪些基础(PHP是什么)

榆林学习php需要哪些基础&#xff0c;想多学一门知识&#xff0c;陕西PHP培训对我们都是大有裨益的&#xff0c;紧接着就去了解下php代码运行方式有哪些&#xff0c;php常用框架有哪些&#xff0c;php为啥遭到它行鄙视&#xff0c;PHP是什么&#xff0c;php的性质有哪些&#x…

oracle 11gr2 asm安装,OEL6.1下oracle 11gr2 ASM安装

oracle 11gr2下asm与以往不同&#xff0c;是使用grid安装包来完成安装与配置&#xff0c;在11.2.0.3的安装包中&#xff0c;使用第三个安装包&#xff0c;解压以后进行以下配置&#xff1a;1. Asm相关用户及组配置/usr/sbin/groupadd -g 502 oper/usr/sbin/groupadd -g 600 asm…

oracle 12配置安全与更新,Oracle 12c 数据库安全核心技术讨论

Oracle AdvancedSecurity新功能 >Oracle Data RedactionOracle Data Redaction对应用户权限的实时访问控制根据用户的权限以及客户端信息&#xff0c;Redaction实时数据修正应用代码代表在不必要的数据库中完成列访问的控制根据客服中心以及技术支持的职责不同&#xff0c;对…

oracle11gR版本GI中新增,Oracle11g新特性MemberKillEscalation简介

从oracle 11gR1 开始&#xff0c;Member Kill Escalation的出现成功的解决了前面提到的情况。当实例eviction在指定的时间内(默认20秒)不能首先我们介绍一下历史。在Oracle 9i/10g 中&#xff0c;如果一个数据库实例需要驱逐(evict, alert 文件中会出现ora-29740错误)另一个实例…

linux命令为什么这么快,为什么这么多Linux用户更喜欢命令行而不是GUI?

为什么这么多 Linux 用户更喜欢 CLI 而非 GUI&#xff1f; 上次我在 Reddit 关注该问题时&#xff0c;遇到了一些有帮助的投稿&#xff1a;“处于相同的原因我更喜欢谈论指指点点和七嘴八舌。 可以很好的传达并给出很好的反馈。这不是一团糟&#xff0c;而是富有诗意的精确。 你…

mac os linux 桌面快捷键,Mac之快捷键

接触Mac不久&#xff0c;很多东西都没了解过&#xff0c;对于快捷键完全不熟悉&#xff0c;查了些资料&#xff0c;顺便做下笔记&#xff5e;&#xff5e;&#xff5e;按键符号Shift&#xff1a;⇧Ctrl&#xff1a;⌃Alt(Option)&#xff1a;⌥Command&#xff1a;⌘Mac按键符号…

linux 等待进程,Linux 进程等待队列

Linux内核的等待队列是以双循环链表为基础数据结构&#xff0c;与进程调度机制紧密结合&#xff0c;能够用于实现核心的异步事件通知机制。在这个链表中&#xff0c;有两种数据结构&#xff1a;等待队列头(wait_queue_head_t)和等待队列项(wait_queue_t)。等待队列头和等待队列…