面试官:AtomicInteger是如何保证线程安全?

c6a99d046d28ed4719ef4cadbfaf83fe.png

blog.csdn.net/nanhuaibeian/article/details/120936139

一、为什么引入 AtomicInteger ?

谈到线程安全,会首先想到了synchronized 和 Lock,但是这种方式又有一个名字,叫做互斥锁,一次只能有一个持有锁的线程进入,再加上还有不同线程争夺锁这个机制,效率比较低,所以又称 悲观锁

与之相对应,就有了 乐观锁 的概念:它不加锁去完成某项操作,如果因为冲突失败就重试,直到成功为止。

AtomicInteger 保证线程安全就是使用了乐观锁,所以相对于悲观锁,效率更高。

在有多个线程同时使用CAS操作一个变量时,只有一个会胜出并成功更新,其余均会失败。失败的线程不会被挂起,仅被告知失败,并且允许再次尝试,当然,也允许失败的线程放弃操作

二、AtomicInteger 原理分析

1. 具体使用

假如我们想实现一个功能来统计网页访问量,可以使用 count++ 来统计访问量,但是这个自增操作不是线程安全的。

加锁实现:

class Counter {private volatile int count = 0;public synchronized void increment() {count++;}public int getCount() {return count;}
}

AtomicInteger 实现:

class Counter {//使用AtomicInteger之后,不需要加锁,也可以实现线程安全。private AtomicInteger count = new AtomicInteger();public void increment() {count.incrementAndGet();}public int getCount() {return count.get();}
}

2. 原理分析

AtomicInteger 类中定义的属性:

// setup to use Unsafe.compareAndSwapInt for updatesprivate static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static {try {valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}

Unsafe是JDK内部的工具类,主要实现了平台相关的操作

sun.misc.Unsafe 是JDK内部用的工具类。它通过暴露一些Java意义上说“不安全”的功能给Java层代码,来让JDK能够更多的使用Java代码来实现一些原本是平台相关的、需要使用native语言(例如C或C++)才可以实现的功能。该类不应该在JDK核心类库之外使用。

简单来说:这段代码是为了获取value在堆内存中的偏移量

Value的定义:

private volatile int value;

volatile 主要特性有两点:防止重排序;实现内存可见性

内存可见性的作用是当一个线程修改了共享变量时,另一个线程可以读取到这个修改后的值

用CAS操作实现原子性:

AtomicInteger中有很多方法,例如

  • incrementAndGet() 相当于i++ ;

  • getAndAdd() 相当于i+=n 。

从源码中我们可以看出这几种方法的实现很相似,这里主要分析incrementAndGet()方法的源码

public final int incrementAndGet() {for (;;) {int current = get();int next = current + 1;if (compareAndSet(current, next))return next;}}public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}

incrementAndGet() 方法实现了自增的操作。

核心实现是先获取当前值和目标值(也就是current +1),如果compareAndSet(current, next) 返回成功则该方法返回目标值。

那么compareAndSet是做CAS操作

每次从内存中根据内存偏移量(valueOffset)取出数据,将取出的值跟expect 比较,如果数据一致就把内存中的值改为update,如果数据不一致说明内存中的数据已经有过更新,此时就进行回滚(expect值不生效)操作。

这样使用CAS的方法就保证了原子操作

Java中的 AtomicLong、AtomicBoolean 等方法的基本原理和思想跟AtomicInteger基本相同

三、总结

(1)用volatile关键字修饰 value 字段,保证了 value 字段对各个线程的可见性,各线程读取value字段时,会先从主从把数据同步到工作内存中,这样保证可见性

(2)Unsafe 实现操作原子性,用户在使用时无需增加额外的同步操作,compareAndSetInt方法是一个CAS操作,用native关键字修饰

原理:先比较内存中的值与expected是否一致,一致的前提下才赋予新的值x,此时返回true,否则返回false

a57fff809d8de0b4c962e9d3fc5b1ef1.gif

往期推荐

029ec2d876b52cfa74cbdcd599d84d1e.png

如何保证数据库和缓存双写一致性?


002829ded9a1ca06ffb653da6fc2646e.png

Spring官方推荐的@Transactional还能导致生产事故?


fee67f74ae465cc1e3ec648b7126a950.png

MySQL 精选 60 道面试题(含答案)


29c475861036d01135c944e8ccb58ac4.gif

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

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

相关文章

机器学习 训练验证测试_测试前验证| 机器学习

机器学习 训练验证测试In my previous article, we have discussed about the need to train and test our model and we wrote a code to split the given data into training and test sets. 在上一篇文章中,我们讨论了训练和测试模型的必要性,并编写了…

如何判断线程池已经执行完所有任务了?

作者 | 磊哥来源 | Java面试真题解析(ID:aimianshi666)转载请联系授权(微信ID:GG_Stone)很多场景下,我们需要等待线程池的所有任务都执行完,然后再进行下一步操作。对于线程 Thread …

IRCTC的完整形式是什么?

IRCTC:印度铁路餐饮和旅游公司 (IRCTC: Indian Railways Catering and Tourism Corporation) IRCTC is an abbreviation of Indian Railways Catering and Tourism Corporation. It is a subsidiary of the Indian Railway established by the Ministry of Railways…

分布式锁的 3 种实现方案!

前言 大家好,我是磊哥。今天跟大家探讨一下分布式锁的设计与实现。希望对大家有帮助,如果有不正确的地方,欢迎指出,一起学习,一起进步哈~分布式锁概述数据库分布式锁Redis分布式锁Zookeeper分布式锁三种分布式锁对比1.…

java学习笔记16--异常

java学习笔记16--异常 异常 异常时导致程序中断运行的一种指令流,如果不对异常进行正确的处理,则可能导致程序的中断执行,造成不必要的损失, 所以在程序的设计中必须要考虑各种异常的发生,并正确的做好相应的处理&am…

线程安全问题的 3 种解决方案!

作者 | 磊哥来源 | Java面试真题解析(ID:aimianshi666)转载请联系授权(微信ID:GG_Stone)线程安全是指某个方法或某段代码,在多线程中能够正确的执行,不会出现数据不一致或数据污染的…

一文读懂MySQL查询语句的执行过程

需要从数据库检索某些符合要求的数据,我们很容易写出 Select A B C FROM T WHERE ID XX 这样的SQL,那么当我们向数据库发送这样一个请求时,数据库到底做了什么?我们今天以MYSQL为例,揭示一下MySQL数据库的查询过程&a…

synchronized底层是如何实现的?

作者 | 磊哥来源 | Java面试真题解析(ID:aimianshi666)转载请联系授权(微信ID:GG_Stone)想了解 synchronized 是如何运行的?就要先搞清楚 synchronized 是如何实现?synchronized 同步…

单例模式 4 种经典实现方法

0.前言 如果你去问一个写过几年代码的程序员用过哪些设计模式,我打赌,90%以上的回答里面会带【单例模式】。甚至有的面试官会直接问:说一下你用过哪些设计模式,单例就不用说了。你看,连面试官都听烦了,火爆…

CSRF简单介绍及利用方法-跨站请求伪造

0x00 简要介绍 CSRF(Cross-site request forgery)跨站请求伪造,由于目标站无token/referer限制,导致攻击者可以用户的身份完成操作达到各种目的。根据HTTP请求方式,CSRF利用方式可分为两种。 0x01 GET类型的CSRF 这种类…

虾皮二面:什么是零拷贝?如何实现零拷贝?

前言 零拷贝是老生常谈的问题啦,大厂非常喜欢问。比如Kafka为什么快,RocketMQ为什么快等,都涉及到零拷贝知识点。最近技术讨论群几个伙伴分享了阿里、虾皮的面试真题,也都涉及到零拷贝。因此本文将跟大家一起来学习零拷贝原理。1.…

各大框架都在使用的Unsafe类,到底有多神奇?

前言 几乎每个使用 Java开发的工具、软件基础设施、高性能开发库都在底层使用了sun.misc.Unsafe,比如Netty、Cassandra、Hadoop、Kafka等。Unsafe类在提升Java运行效率,增强Java语言底层操作能力方面起了很大的作用。但Unsafe类在sun.misc包下&#xff0…

Codis 分布式缓存部署

为什么80%的码农都做不了架构师?>>> 环境介绍: 1:机器三台 ,IP/hostname 如下, hostname的设置很重要zookeeper / codis的通信都会用到,所以要配置好三台机器的hosts文件. 10.221.8.220 机器的hostname为 Redis1 10.221.8.221 机器的hostname为 Redis…

怎么解决MySQL死锁问题的?

咱们使用 MySQL 大概率上都会遇到死锁问题,这实在是个令人非常头痛的问题。本文将会对死锁进行相应介绍,对常见的死锁案例进行相关分析与探讨,以及如何去尽可能避免死锁给出一些建议。话不多说,开整!什么是死锁死锁是并…

Apache cxf JaxRs基本应用

2019独角兽企业重金招聘Python工程师标准>>> 在前一篇中&#xff0c;我们完成了《Apache cxf JaxWs基本应用》 的编写&#xff0c;我们现在实现一个Restful风格的Cxf 。 一、我们首先依旧是基于Maven project配置pom.xml的依赖 [html] view plaincopyprint? <pr…

白嫖1年阿里云,反手就搭一个Java环境

作者 | 磊哥来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;早上收到阿里云小姐姐的消息&#xff0c;阿里云有搞事情了&#xff0c;这次是送一年的阿里云 ECS 服务器。有便宜不占王八蛋…

synchronized和ReentrantLock的5个区别!

作者 | 磊哥来源 | Java面试真题解析&#xff08;ID&#xff1a;aimianshi666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;在 Java 中&#xff0c;常用的锁有两种&#xff1a;synchronized&#xff08;内置锁&#xff09;和 ReentrantLock&a…

《小强升职记》读后感和思维导图

语言幽默轻松&#xff0c;寓教于乐&#xff0c;看完之后有挽起袖子大干一场的冲动&#xff0c;但是诚如书中所言&#xff0c;“不做收藏家&#xff0c;要做建筑工”&#xff0c;实践和坚持才能有所收获。第一次画思维导图(′▽〃)Xmind格式文件转载于:https://www.cnblogs.com/…

oppo后端16连问

前言 大家好&#xff0c;我是磊哥。最近有位读者去面试了oppo&#xff0c;给大家整理了面试真题的答案。希望对大家有帮助哈&#xff0c;一起学习&#xff0c;一起进步。聊聊你印象最深刻的项目&#xff0c;或者做了什么优化。你项目提到分布式锁&#xff0c;你们是怎么使用分布…

实战!阿里神器 Seata 实现 TCC 模式解决分布式事务

今天这篇文章介绍一下Seata如何实现TCC事务模式&#xff0c;文章目录如下&#xff1a;目录什么是TCC模式&#xff1f;TCC&#xff08;Try Confirm Cancel&#xff09;方案是一种应用层面侵入业务的两阶段提交。是目前最火的一种柔性事务方案&#xff0c;其核心思想是&#xff1…