8.volatile为啥不能保证原子性?

简介: 8.volatile为啥不能保证原子性?

volatile为什么不能保证原子性


小陈:老王,快来快来,上一篇结尾说volatile不能保证原子性,我现在迫不及待了...

老王:哈哈,来了,马上开搞......

老王:按照惯例,我还是先来给你画张图:

还是以 i++ 的那个例子为例,volatile int i = 0,假如两个线程A线程B同时对 i 进行 ++ 操作如下:

image.png

上图存在一种情况就是,线程A线程B如果几乎同时读取 i = 0 到自己的工作内存中。

线程A执行 i++  结果后将 i = 1 赋值给工作内存;但是这个时候还没来的将最新的结果刷新回主内存的时候线程B读取主内存的旧值 i = 0 ,然后执行use指令将 i = 0的值传递给线程B去进行操作了。

即使这个时候线程A立即将 i = 1刷入主内存那也晚了线程B已经使用旧值 i = 0进行操作了,像这种情况计算结果就不对了。

老王:小陈,我上面的那个图讲解,你可以听懂嘛?

小陈:嗯嗯,看图解释就是,线程Ai ++  结果, 也就是 i = 1还没刷回主内存线程B就执行 use指令将 i = 0传递给cpu了 ,导致线程B使用的就旧的值 i = 0去进行操作,得到结果是错的。


怎样才能保证原子性?


小陈:那如果要保证原子性,应该是怎么样子的?

老王:如果要保证原子性的话,落到底层实际还是需要进行加锁的,需要保证任意时刻只能有一个线程能执行成功。

比如在硬件层次或者对总线进行加锁,使得某一时刻只能有一个线程能执行i++ 操作,这样才能是不被中断的,才是原子性的。

现在现在这种情况,相当于就是两个线程同时进行了 i++操作线程Ai++ 操作还没结束;线程Bi++ 操作就也同时进行着,这种情况不是原子的。

小陈:哦,是不是可以这么理解:

如果要保证原子性的话,同一时刻只能有一个线程或者CPU能够执行成功底层是需要对硬件进行加锁的,只有某个CPU或者线程锁定了,享有独占的权限,那么它的操作才能是不被其它CPU或者线程打断的。

老王:没错,就是这个道理;你只有在硬件级别加锁了之后,享有独占的权限你的操作才能是不被其它CPU或线程打断的。

小陈:好的,老王,这么说我就理解了。

老王:这一篇对volatile不能保障原子性的解释,你再多看看几遍,多理解一下。再对之前的文章再复习复习,包括内存屏障、java内存模型、MESI一致性协议等知识,从下一章看是我们就要进入新的学习了。

小陈:好啊老王,下面的篇章我们要学习什么知识啊?

老王:下面我们就要进入synchronized的学习了....

相关文章
|
缓存 算法
07、Netty学习笔记—(聊天业务优化:参数调优)(二)
07、Netty学习笔记—(聊天业务优化:参数调优)(二)
07、Netty学习笔记—(聊天业务优化:参数调优)(二)
|
存储 Kubernetes NoSQL
无锁队列实现及使用场景
无锁队列实现及使用场景
|
负载均衡 Java API
Spring Cloud 面试题及答案整理,最新面试题
Spring Cloud 面试题及答案整理,最新面试题
468 1
|
存储 NoSQL Java
使用Redisson RLock锁防止定时任务短周期重复执行
在开发定时任务时,如果任务执行周期较短,可能会导致任务在前一次执行尚未完成时就再次触发,从而产生重复执行的问题。为了解决这个问题,我们可以借助Redisson的RLock锁机制,确保任务只有在前一次执行完成后才能再次执行。本文将介绍如何使用Redisson RLock锁来避免定时任务的重复执行。
683 0
使用Redisson RLock锁防止定时任务短周期重复执行
|
开发工具 git
IDEA 错误运行’Application’: !invalid format: `命令行过长
刚刚在Git下拉的项目,启动的时候就报错了。记录一下
3177 0
IDEA 错误运行’Application’: !invalid format: `命令行过长
|
缓存 JavaScript Java
常见java OOM异常分析排查思路分析
Java虚拟机(JVM)遇到内存不足时会抛出OutOfMemoryError(OOM)异常。常见OOM情况包括:1) **Java堆空间不足**:大量对象未被及时回收或内存泄漏;2) **线程栈空间不足**:递归过深或大量线程创建;3) **方法区溢出**:类信息过多,如CGLib代理类生成过多;4) **本机内存不足**:JNI调用消耗大量内存;5) **GC造成的内存不足**:频繁GC但效果不佳。解决方法包括调整JVM参数(如-Xmx、-Xss)、优化代码及使用高效垃圾回收器。
555 15
常见java OOM异常分析排查思路分析
|
4月前
|
存储 Java API
MinIO Java SDK 7.1.4 升级到 8.5.17 需要注意什么
现在我需要你帮我分析对比这个两个sdk在对外的接口设计上是否有不兼容的变更
296 5
|
安全 Java
深拷贝和浅拷贝的区别
深拷贝和浅拷贝的区别
|
11月前
|
Cloud Native 前端开发 JavaScript
前端开发者必看:不懂云原生你就OUT了!揭秘如何用云原生技术提升项目部署与全栈能力
【10月更文挑战第23天】随着云计算的发展,云原生逐渐成为技术热点。前端开发者了解云原生有助于提升部署与运维效率、实现微服务化、掌握全栈开发能力和利用丰富技术生态。本文通过示例代码介绍云原生在前端项目中的应用,帮助开发者更好地理解其重要性。
290 0
|
12月前
|
Java 编译器 Spring
Spring AOP 和 AspectJ 的区别
Spring AOP和AspectJ AOP都是面向切面编程(AOP)的实现,但它们在实现方式、灵活性、依赖性、性能和使用场景等方面存在显著区别。‌
378 2