final的安全发布
final的安全发布
两个关键字“发布”“安全”
所谓发布通俗一点的理解就是创建一个对象,使这个对象能被当前范围之外的代码所使用
比如Object o = new Object();
然后接下来使用对象o
但是对于普通变量的创建,之前分析过,大致分为三个步骤:
1、分配内存空间
2、将o指向分配的内存空间
3、调用构造函数来初始化对象
这三个步骤不是原子的,如果执行到第二步,还没有进行初始化,此时对象已经不是null了,如果被其他代码访问,这将收获一个错误的结果。
或者说对象尚未完全创建就被使用了,其他线程看到的结果可能是不一致的,这就是不安全的发布
根本原因就是JVM创建对象的过程涉及到分配空间、指针设置、数据初始化等步骤,并不是同步的,涉及到主存与缓存、处理器与寄存器等,可见性没办法得到保障
所以说,什么是安全发布,简单理解就是对象的创建能够保障在被别人使用前,已经完成了数据的构造设置,或者说一个对象在使用时,已经完成了初始化。
不幸的是,Java对此并没有进行保障,你需要自己进行保障,比如synchronized关键字,原子性、排他性就可以做到这一点
不安全的发布实例
怎么保障安全发布?有几种方法:
一种是刚才提到的锁机制,通过加锁可以保障中间状态不会被读取
另外还有:
1、借助于volatile或者AtomicReference声明对象
2、借助于final关键字
3、在静态初始化块中,进行初始化(JVM会保障)
4、将对象引用保存到一个由锁保护的域中
5、借助AtomicReference
很显然,对于锁机制,那些线程安全的容器比如ConcurrentMap,也是满足这条的,所以也是安全发布
对于final,当你创建一个对象时,使用final关键字能够使得另一个线程不会访问到处于“部分创建”的对象
因为:当构造函数退出时,final字段的值保证对访问构造对象的其他线程可见
如果某个成员是final的,JVM规范做出如下明确的保证:
一旦对象引用对其他线程可见,则其final成员也必须正确的赋值
所以说借助于final,就如同你对对象的创建访问加锁了一般,天然的就保障了对象的安全发布。
对于普通的变量,对象的内存空间分配、指针设置、数据初始化,和将这个变量的引用赋值给另一个引用,之间是可能发生重排序的,所以也就导致了其他线程可能读取到不一致的中间状态
但是对于final修饰的变量,JVM会保障顺序
不会在对final变量的写操作完成之前,与将变量引用赋值给其他变量之间进行重排序,也就是final变量的设置完成始终会在被读取之前
final除了不可变的定义之外,还与线程安全发布息息相关
借助于final,可以达到对象安全发布的保障,只需要借助于final,不在需要任何额外的付出,他能够保障在多线程环境下,总是能够读取到正确的初始化的值
所以,如果你不希望变量后续被修改,你应该总是使用final关键字
而且,很显然在某些场景下,final也可以解决一定的安全问题
实例
使用synchronized锁的时候,作为锁的对象最好要加上final修饰符,因为可能线程会改变锁变量持有的具体的对象。
demo如下:
public class Test02 {
static Object lock = new Object();
public static void main(String[] args) {Thread t1 = new Thread(() -> {lock = new Object();synchronized (lock) {for (int i = 0; i < 10; i++) {try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("A");}}});Thread t2 = new Thread(() -> {lock = new Object();synchronized (lock) {for (int i = 0; i < 10; i++) {try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("B");}}});t1.start();t2.start();
}
}
但是要是把锁改成final的。代码如下:
public class Test02 {static final Object lock = new Object();public static void main(String[] args) {Thread t1 = new Thread(() -> {
// lock = new Object(); // 编译出错,final不能修改synchronized (lock) {for (int i = 0; i < 10; i++) {try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("A");}}});Thread t2 = new Thread(() -> {
// lock = new Object();synchronized (lock) {for (int i = 0; i < 10; i++) {try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("B");}}});t1.start();t2.start();}
}
实例参考:https://juejin.cn/post/7104070219806539806
原理参考:https://www.cnblogs.com/noteless/p/10416678.html
相关文章:
final的安全发布
final的安全发布 两个关键字“发布”“安全” 所谓发布通俗一点的理解就是创建一个对象,使这个对象能被当前范围之外的代码所使用 比如Object o new Object(); 然后接下来使用对象o 但是对于普通变量的创建,之前分析过,大致分为三个步骤&am…...
3易懂AI深度学习算法:长短期记忆网络(Long Short-Term Memory, LSTM)生成对抗网络 优化算法进化算法
继续写:https://blog.csdn.net/chenhao0568/article/details/134920391?spm1001.2014.3001.5502 1.https://blog.csdn.net/chenhao0568/article/details/134931993?spm1001.2014.3001.5502 2.https://blog.csdn.net/chenhao0568/article/details/134932800?spm10…...
云计算 云原生
一、引言 云计算需要终端把信息上传到服务器,服务器处理后再返回给终端。在之前人手一台手机的情况下,云计算还是能handle得过来的。但是随着物联网的发展,什么东西都要联网,那数据可就多了去了,服务器处理不过来&…...
深拷贝、浅拷贝 react的“不可变值”
知识获取源–晨哥(现实中的人 嘿嘿) react中如果你想让一个值始终不变 或者说其他操作不影响该值 它只是作用初始化的时候 使用了浅拷贝–改变了初始值 会改变初始值(selectList1) 都指向同一个地址 const selectList1 { title: 大大, value: 1 };con…...
赛宁网安多领域亮相第三届网络空间内生安全发展大会
2023年12月8日,第三届网络空间内生安全发展大会在宁开幕。两院院士、杰出专家学者和知名企业家相聚南京,围绕数字经济新生态、网络安全新范式进行广泛研讨,为筑牢数字安全底座贡献智慧和力量。 大会围绕“一会、一赛、一展”举办了丰富多彩的…...
LintCode 123 · Word Search (DFS字符处理经典题!)
123 Word Search Algorithms Medium Description Given a 2D board and a string word, find if the string word exists in the grid. The string word can be constructed from letters of sequentially adjacent cell, where “adjacent” cells are those horizontally o…...
SpringCloud面试题——Sentinel
一:什么是Sentinel? Sentinel是一个面向分布式架构的轻量级服务保护框架,实现服务降级、服务熔断、服务限流等功能 二:什么是服务降级? 比如当某个服务繁忙,不能让客户端的请求一直等待,应该立刻返回给客户端一个备…...
【精选】 VulnHub (超详细解题过程)
🍬 博主介绍👨🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏…...
数据结构与算法-Rust 版读书笔记-2线性数据结构-队列
数据结构与算法-Rust 版读书笔记-2线性数据结构-队列 1、队列:先进先出 队列是项的有序集合,其中,添加新项的一端称为队尾,移除项的另一端称为队首。一个元素在从队尾进入队列后,就会一直向队首移动,直到…...
Android Kotlin Viewbinding封装
目录 Viewbinding配置 Activity封装 Activity使用 Fragment封装 Fragment使用 Dialog封装 Dialog使用 Viewbinding配置 android { viewBinding { enabled true } } Activity封装 import android.os.Bundle import android.view.LayoutInflater import androidx.ap…...
Flutter:web项目跨域问题解决
前后端解决系列 文章目录 一、Flutter web客户端解决本地环境调试跨域问题二、Flutter web客户端解决线上环境跨域问题 一、Flutter web客户端解决本地环境调试跨域问题 就一句命令【--web-browser-flag "--disable-web-security"】,用来屏蔽浏览器域名请…...
汽车标定技术(十二)--A2L文件生成的方法
目录 1.工具生成 1.1 CANape/ASAP2 Studio 1.2 ASAP2ToolKit 1.3 Matlab/Simulink 2.手写A2L要点 3.小结 A2L文件的制作一直以来是一个很少有人关注的方向,不管是标定工程师还是Slave协议栈的开...
《PySpark大数据分析实战》-03.了解Hive
📋 博主简介 💖 作者简介:大家好,我是wux_labs。😜 热衷于各种主流技术,热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员(PCTA)、TiDB数据库专家(PCTP…...
经验分享|MySQL分区实战(RANGE)
概述 分区概述 在 MySQL 中, InnoDB存储引擎长期以来一直支持表空间的概念。在 MySQL 8.0 中,同一个分区表的所有分区必须使用相同的存储引擎。但是,也可以为同一 MySQL 服务器甚至同一数据库中的不同分区表使用不同的存储引擎。 通俗地讲…...
Arrays.asList() 和 Collections.singletonList()
Arrays.asList() 和 Collections.singletonList() 概述 List 是我们使用Java时常用的集合类型。众所周知,我们可以轻松地在一行中初始化列表。例如,当我们想要初始化一个只有一个元素的List时,我们可以使用Arrays.asList(&#…...
Firmware Analysis Plus (Fap)固件模拟安装教程(最新)
最近在搞IoT的研究,但是难在设备比较难弄,只有固件,而没有设备,买吧,又太费钱,不划算。好在有很多项目可以在模拟环境中运行固件。但是几乎没有一个平台能够模拟所有硬件设备。IoT产品的架构也不尽相同。 …...
使用包、Crate 和模块管理项目(上)
目录 1、包和Crate 2、定义模块来控制作用域与私有性 2.1 在模块中对相关代码进行分组 3、引用模块项目的路径 3.1 使用 pub 关键字暴露路径 二进制和库 crate 包的最佳实践 3.2 super 开始的相对路径 3.3 创建公有的结构体和枚举 Rust 有许多功能可以让你管理代码的组…...
【Kotlin】
Lambda 就是一小段可以作为参数传递的代码。 因为正常情况下,我们向某个函数传参时只能传入变量,而借助Lambda 却允许传入一小段代码。 Lambda 表达式的语法结构: {参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}首先,最外…...
JavaDay17
创建不可变集合 import java.util.Iterator; import java.util.List;public class Test {public static void main(String[] args) {/*创建不可变的List集合* "张三" "李四" "王五" "赵六*///一旦创建之后 是无法进行修改的 在下面的代码…...
Python爬取酷我音乐
🎈 博主:一只程序猿子 🎈 博客主页:一只程序猿子 博客主页 🎈 个人介绍:爱好(bushi)编程! 🎈 创作不易:喜欢的话麻烦您点个👍和⭐! 🎈…...
League Akari:英雄联盟玩家的智能游戏伴侣,如何用开源工具提升你的竞技体验
League Akari:英雄联盟玩家的智能游戏伴侣,如何用开源工具提升你的竞技体验 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit …...
Graphormer效果展示:PCQM4M榜单SOTA级分子属性预测结果集
Graphormer效果展示:PCQM4M榜单SOTA级分子属性预测结果集 1. 模型概述 Graphormer是一种基于纯Transformer架构的图神经网络,专门为分子图(原子-键结构)的全局结构建模与属性预测而设计。该模型在OGB、PCQM4M等分子基准测试中表…...
iOS高级开发工程师技术体系与民航行业实践深度解析
第一章 iOS开发技术核心体系 1.1 Swift与Objective-C双语言生态 现代iOS开发需要掌握两种核心语言的技术特点: // Swift类型安全示例 enum FlightStatus {case scheduled, departed, landed, canceled }var currentStatus: FlightStatus = .scheduled// 编译器会阻止非法状…...
百度网盘提取码智能获取工具:提升资源获取效率的技术方案
百度网盘提取码智能获取工具:提升资源获取效率的技术方案 【免费下载链接】baidupankey 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 在数字资源爆炸的今天,百度网盘作为主流文件分享平台,已成为学习资料、工作文件和媒…...
漫画脸描述生成保姆级教程:如何调试生成结果提升SD绘图匹配度
漫画脸描述生成保姆级教程:如何调试生成结果提升SD绘图匹配度 你是不是也遇到过这样的情况:脑子里有个超棒的二次元角色形象,但用AI绘图工具画出来总是差那么点意思?要么发型不对,要么表情奇怪,要么服装细…...
保姆级教程:用Nordic NRF52832搞定SIF一线通协议收发(附完整代码)
Nordic NRF52832实战:SIF一线通协议全双工通信开发指南 在物联网设备开发中,单线通信协议因其布线简单、成本低廉而广受欢迎。SIF(Single Interface)作为一种轻量级一线通协议,特别适合传感器与控制器之间的短距离数据…...
测试右移的复仇:上线后bug如何让公司赔光融资
当质量防线在“最后一公里”失守在软件交付的终点线前,测试团队常被一种“虚假的安全感”所笼罩。测试环境用例全绿,性能压测数据达标,验收报告签字盖章,一切似乎都指向一个平稳的上线。然而,当代码被部署到生产环境&a…...
保姆级教程:手把手教你下载SEED-VIG脑电数据集(附Gitee国内镜像地址)
从零到一:SEED-VIG脑电数据集的完整获取与解析指南 第一次接触SEED-VIG数据集时,我花了整整三天时间才搞明白如何正确下载和解析这个2.9GB的庞然大物。作为研究驾驶疲劳检测的重要资源,这个数据集的价值毋庸置疑,但获取过程却让不…...
【Mojo+Python企业级混合编程实战指南】:20年架构师亲授3大高频场景落地方法论
第一章:Mojo与Python混合编程的企业级价值全景图Mojo 是一种专为 AI 原生系统设计的现代系统编程语言,兼具 Python 的表达力与 C/Rust 级别的性能。在企业级 AI 工程实践中,Mojo 并非旨在替代 Python,而是以“无缝互操作”为核心理…...
Legacy-iOS-Kit:让旧设备重获新生的开源解决方案
Legacy-iOS-Kit:让旧设备重获新生的开源解决方案 【免费下载链接】Legacy-iOS-Kit An all-in-one tool to restore/downgrade, save SHSH blobs, jailbreak legacy iOS devices, and more 项目地址: https://gitcode.com/gh_mirrors/le/Legacy-iOS-Kit 当你的…...
