setnx是原子操作吗_谈谈Volatile关键字?为什么不能保证原子性?用什么可以替代?为什么?...

fa23b941472cc8e5dfa5efd7f1cdb691.png

大家好,欢迎关注我的公众号码猿bug,需要资料的话可以加我微信好友。

再谈volatile关键字之前,首先必须聊聊JMM内存模型!

JMM主要的特性:可见性、原子性,顺序性

Java 虚拟机规范试图定义一种 Java 内存模型(JMM),来屏蔽掉各种硬件和操作系统的内存访问差异,让 Java 程序在各种平台上都能达到一致的内存访问效果。简单来说,由于 CPU 执行指令的速度是很快的,但是内存访问的速度就慢了很多,相差的不是一个数量级,所以搞处理器的那群大佬们又在 CPU 里加了好几层高速缓存。在 Java 内存模型里,对上述的优化又进行了一波抽象。JMM 规定所有变量都是存在主存中的,类似于上面提到的普通内存,每个线程又包含自己的工作内存,方便理解就可以看成 CPU 上的寄存器或者高速缓存。所以线程的操作都是以工作内存为主,它们只能访问自己的工作内存,且工作前后都要把值在同步回主内存。

网上找的一些定义:

11a514a3943be773e8fab4f3e9b93bfa.png

55c818756b85fc0ddda1773c80e08292.png

简单描述如下:

  • 主存存放线程需要操作的变量,但线程并不直接操作主存。
  • 每个线程读取主存变量都是先拷贝一份到工作内存中,不同线程工作内存互不干扰。
  • 线程修改了工作内存后,再写回主存中。
  • 每次从主存读写的过程都需要经过原子性操作。

简单知道了java的内存模型,那开始聊聊volatile关键字。volatile关键字有三大特性:

①可见性

②不保证原子性

③禁止指令重排

首先要知道volatile是java虚拟机提供的轻量级的同步机制,volatile的可见性是由jvm发送一条lock前缀的汇编指令实现的。volatile关键字是修饰成员变量的,也就是说,如果一个成员变量加了volatile关键字,就会告诉编译器和jvm的内存模型,这个变量是对所有线程共享的,可见性每次JVM都会读取最新写入的值并使其最新值在所有的cpu可见。volatile可以保证线程的可见性并且提供了一定的顺序性,但是无法保证原子性。在JVM底层volatile是采用内存屏障来实现的。使用了volatile关键字就好像是线程直接操作了主内存。

为什么不能保证原子性呢?

在我们的程序中,即使加了volatile也不能保证原子性,有一种粗暴的解决办法,就是加我们的synchronized同步锁,但是这种锁太重了。简单画个图演示为什么不能保证原子性。

在程序中的i++操作,是不能保证原子性的.

8134d1b2a74dd783625ac461ee9b4b2a.png

那原子性和可见性不是就冲突了吗?不冲突

因为volatile 的可见性只能对应l原子性, a=1是原子性,而a++实际上是a=a+1 是非原子性的,所以会导致你说的情况,这时候就要引入同步,强制将a++转化为原子性。

那除了synchronized还有其他解决办法吗?

那就是大名鼎鼎的JUC包下的AtomicInteger,写一小段程序说明:

AtomicInteger 

那为什么用AtomicInteger就能保证原子性呢?因为他的底层是CAS,接下来就要说说什么是cas了。

cas是compare and set的缩写,比较并交换,unsafe是cas的核心类,cas的底层是靠的unsafe类来保证原子性的,unsafe是jvm下的rt.jar的运行jar包里面。

跟进源代码可以看见这段代码:

public final int getAndIncrement(){return unsafe.getAndAddInt(this,1);//这个1是值的valueoffset:内存地址偏移量
}

还靠的是一段do while循环,顾名思义,又叫自旋锁

f6fe1ec31079feefc7175c25d9ec81cc.png

这时候就应该思考,为什么在没有加锁的情况下,还能保证线程安全呢?

①因为atomicInteger借助了UnSafe提供的CAS操作能够保证数据更新的时候是线程安全的,那么为什么借助了unsafe就能保证线程安全呢?以下总结出自我的笔记

4066ca99e4803449c02becebf6cc58a7.png

d64805d8d066655a102dcafa91c57fbe.png

因为cas并发原语体现在JAVA语言中就是sun.misc.Unsafe类中的各个方法。调用Unsafe类中的CAS方法,JVM会帮我们实现汇编指令,这是一种完全依赖的硬件功能。通过他实现了原子操作。并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题,保证了线程安全。

下一篇文章中会继续讨论CAS的缺点以及volatile的应用场景。技术小白一枚,希望各位大佬指出错误,互相讨论。

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

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

相关文章

360 屏蔽ajax,怎么在easy ui做全局Ajax拦截啊?

满意答案egiuas2014.08.13采纳率:53% 等级:9已帮助:167人在web.xml中定义一个全局过滤器拦截所有请求:自定义filter your difine filter name /* 后台代码:过滤器中获取session用户对象 如果为空,返回超…

c++的STL

STL,英文全称 standard template library,中文可译为标准模板库或者泛型库,其包含有大量的模板类和模板函数,是 C 提供的一个基础模板的集合,用于完成诸如输入/输出、数学计算等功能。 泛型编程指编写完全一般化并可重…

【招聘(深圳)】TCL通讯科技控股有限公司

Windows 架构师 (25-35K)工作职责:1. 负责windows平台产品功能的需求分析、系统设计和规划;2. 负责Windows 平台关键功能技术预研、技术攻坚、性能优化。岗位核心价值:智能连接中WINDOWS投屏部分的架构技术分解和技术攻坚。关键工作任务&…

用python排序算法_Python - 八大排序算法

1、序言 本文使用Python实现了一些常用的排序方法。文章结构如下: 1.直接插入排序 2.希尔排序 3.冒泡排序 4.快速排序 5.简单选择排序 6.堆排序 7.归并排序 8.基数排序 上述所有的排序均写在一个Python自定义类中,作为成员函数。 2、排序方法详细介绍 1.…

剑指offer-数组中的重复的数字-p39

数组 c中的STL中的vector (STL中的vector每次扩容量时,新的容量都是之前一次的两倍) 在c/c中,数组和指针是相互关联又有区别的两个概念。 关联:当我们声明一个数组时,其数组的名字也是一个指针,该指针指向数组的第一个…

尝鲜!.NET5实操之docker+k8s,这10个坑,你不得不知!

2016年发布了.NET Core第一个正式版本,2020年11月.NET5也正式来临了,技术日新月异,也有点让人应接不暇。在框架设计上,.NET Framework的全家桶理念,培养了一大批的CRUD,而.NET Core转变成了按需使用(Pay fo…

jdk解压版_命令行版的斗地主你玩过没?

相信大家都玩过斗地主游戏,或在现实中斗地主或在电脑和手机上斗地主,但你想过用命令行界面进行斗地主吗?先来张图体验一下:是不是觉得挺有意思,下面就带大家一起玩一下吧~部署命令行版斗地主1 环境准备该项目是基于jav…

c语言——什么时候使用getchar()读取换行符

做题的时候有时会用到getchar()接收换行符,然而让人困惑的是一般使用scanf("%s", str)这样的形式读取字符串的时候似乎并没有考虑这个问题。网上通常会给你讲大道理缓冲区啥的,然后听懂后自己得不得的出结论全看天赋(摊手&#xff…

[项目更新] 集成RabbitMQ队列与EventBus总线

(Blog.Core框架开发情况,着色部分为本次新增)终于项目继续迭代更新了,在开源这两年多,也是感谢每一个支持Blog.Core项目的同学,同时也感谢每一个在生产环境中使用,并提出意见和建议的小伙伴&…

cv2.imread读取图像结果none_python cv2.imread 读取中文路径的图片返回为None的问题

此篇文章首发于我的csdn博客,见原文链接。使用cv2读取图片是常见的事情,但如果,输出图片形状大小时出现报错“ NoneType object has no attribute shape”,后来排查发现读取图片的返回值image为None, 这就说明图片根本…

关于大学计算机相关专业学习路线的见解与分析

推荐阅读: 开学了,计算机的大学生们,送你们一篇经书,希望你们的四年不负年华! 入计算机专业的师弟师妹,别再迷茫了,我整理一份CS的学习路线大全!帮你超越大部分的同学! …

利用模板化应对ERP业务模型的快速变化

源宝导读:ERP这类复杂系统中,业务模型是系统功能的核心抽象,但业务模型对于不同的客户会有差异,也会随着业务发展而变化。虽然可以对业务组件进行复用,但客户定制的成本依然较高,本文将讨论如何利用模板化应…

mockmvc get请求 tm的 一直404_大家快来看看404的兄弟姐妹

码个蛋(codeegg)第 624 次推文作者:xiaoxiunique博客:https://juejin.im/post/5cd2ea425188254459335583做开发的我们肯定少不了跟网络数据打交道,我们都知道,我们进行网络请求,无论成功还是失败,后台都会给…

网传不要升级.NET5的诸多原因,你赞同几个?

.NET5正式发布有十多天,博客园、知乎、技术群都讨论的非常热烈。关于项目是否迁移.NET5的话题讨论的尤为热烈,作为.NET十年老司机要告诉你,.NET5的迁移势在必行,当下就是最好的时机!犹豫项目是否升级到.NET5的&#xf…

sort()函数

sort()函数 标准库里的排序函数的使用方法 I)Sort函数包含在头文件为#include的c标准库中,调用标准库里的排序方法可以不必知道其内部是如何实现的,只要出现我们想要的结果即可! II)Sort函数有三个参数:…

WPF开发的实用小工具 - 快捷悬浮菜单

WPF开发的实用小工具 - 快捷悬浮菜单❝本文由网友投稿,Dotnet9站长整理。站长觉得这小工具很实用,站长家里、公司也在尝试使用了。行文目录:这工具有什么用?正文源码获取及应用下载体验站长的建议1. 这工具有什么用?问…

accdb原有的数据怎么清除_VBA中利用数组对数据批量处理的方法

大家好,今日继续和大家分享VBA编程中常用的常用"积木"过程代码。这些内容大多是我的经验和记录,来源于我多年的经验。今日分享的是NO.225-NO.226,内容是:NO. 225:数组的赋值和回填工作表NO. 226:…

问题 A: 约瑟夫问题(普及第一关模拟)

题目描述 求解约瑟夫(Joseph)问题。有n个小孩围成一圈,给他们从1开始依次编号,从编号为1的小孩开始报数,数到第m个小孩出列,然后从出列的下一个小孩重新开始报数,数到第m个小孩又出列&#xff…

云南河道 kml文件_处理能力提升 4 倍 ,大疆智图 4 天完成 5 公里河道建模

马陵河是江苏省宿迁市老城区一条重要排涝河道,1974 年人工开挖而成,全长 5.2 km,汇水面积 11.6 km,居住人口 13.85 万人。河道水质长期处于黑臭状态,严重影响周边居民日常生活,被称为宿迁的“龙须沟”。宿迁…

linq 查询的结果会开辟新的内存吗?

一:背景 1. 讲故事昨天群里有位朋友问:linq 查询的结果会开辟新的内存吗?如果开了,那是对原序列集里面元素的深拷贝还是仅仅拷贝其引用?其实这个问题我觉得问的挺好,很多初学 C# 的朋友或多或少都有这样的疑…