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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215344.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215344.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215344.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

k8s之身份認證與權限

Kubernetes 中提供了良好的多租戶認證管理機制&#xff0c;如 RBAC、ServiceAccount 還有各種策略等。 通過該文件可以看到已經配置了 RBAC 訪問控制 /usr/lib/systemd/system/kube-apiserver.service 1.1 認證 所有 Kubernetes 集群有兩類用戶&#xff1a;由 Kubernetes 管理的…

mysql數據庫學習筆記(1)

今天開始學mysql數據庫&#xff0c;為什么要學這個呢&#xff0c;因為數據庫可結構化存儲大量的數據信息&#xff0c;方便用戶進行有效的檢索和訪問。數據庫可有效地保持數據信息的一致性、完整性、降低數據冗余。數據庫可滿足應用的共享和安全方面的要求&#xff0c;把數據放在…

java--認識異常、自定義異常

1.異常體系 Error&#xff1a;代表的系統級別錯誤(屬于嚴重問題)&#xff0c;也就是說系統一旦出現問題&#xff0c;sun公司會把這些問題封裝成Error對象給出來&#xff0c;說白了&#xff0c;Error是給sun公司自己用的&#xff0c;不是給我們程序員用的&#xff0c;因此我們開…

MacOS下homebrew的安裝與使用

安裝Homebrew //刪除原來的文件&#xff0c;可以在刪除前查看下Cellar文件夾下已安裝的包,homebrew將工具安裝在這個文件夾下&#xff0c;并在/usr/local/bin下建立連接 sudo -irm -rf /usr/local/Cellar /usr/local/.gi sudo chown -R liudong /usr/local //更新文件屬主為liu…

114. 二叉樹展開為鏈表 --力扣 --JAVA

題目 給你二叉樹的根結點 root &#xff0c;請你將它展開為一個單鏈表&#xff1a; 展開后的單鏈表應該同樣使用 TreeNode &#xff0c;其中 right 子指針指向鏈表中下一個結點&#xff0c;而左子指針始終為 null 。展開后的單鏈表應該與二叉樹 先序遍歷 順序相同。 解題思路 …

通過Ai幫我們寫前端界面設計

現在我要寫一個前端界面&#xff0c;from表單&#xff0c;讓用戶登錄使用的&#xff0c;提交表單之前先分析用戶名和密碼是否填的完成&#xff0c;并且檢查密碼必須滿足 包含大小寫&#xff0c;數字&#xff0c;密碼長度必須在8到20之間&#xff0c;不滿足不可以提交。用戶名必…

ethtool

ethtool ethtool是一個常用的命令行工具&#xff0c;用于配置和查詢以太網接口的驅動程序和硬件參數。它提供了一種簡單的方式來檢查和修改網絡接口的設置&#xff0c;以及獲取與以太網接口相關的統計數據和狀態信息。 ethtool可以執行以下常見的操作&#xff1a; 查詢接口信息…

【Hadoop】修改YARN配置文件

本節需要修改的 YARN 配置文件保存在$HADOOP_HOME/etc/haoop 目錄下&#xff0c;需要修改的文件共有 7 個&#xff0c;分別是&#xff1a;core-site.xml, hadoop-env.sh, hdfs-site.xml, yarn-site.xml, yarn-env.sh, mapred-site.xml, slave. 這些文件的用途&#xff1a; core…

Mysql:慢cpu過高慢sql查詢方法

通過 processlist查詢較為便捷&#xff0c;只是結果的info中只會顯示sql的前100個字符。 show processlist 通過下面語句查詢可顯示當前正在執行的完整sql。 SELECT * FROM information_schema.processlist WHERE COMMAND ‘Query’; 借助navicate數據庫工具的監控功能查詢庫的…

大數據技術2:大數據處理流程

前言&#xff1a;下圖是一個簡化的大數據處理流程圖&#xff0c;大數據處理的主要流程包括數據收集、數據存儲、數據處理、數據應用等主要環節。 1.1 數據收集 大數據處理的第一步是數據的收集。現在的中大型項目通常采用微服務架構進行分布式部署&#xff0c;所以數據的采集需…

【常用字符大全】含emoji表情

常用符號大全 ?????????????▲???↑↓◆◇⊙■□△▽─│??♂♀?????????▼???≈←→?◎☉★☆⊿※¡━┃??ツ?????©?Σ????卐√↖↗●?Θ◤◥︻〖〗┄┆℃℉?????¢€£∞?★?↙↘○?⊕◣◢︼【】┅┇…

Java 中適合使用隊列(Queue)的場景

在 Java 中&#xff0c;隊列&#xff08;Queue&#xff09;適合用于以下場景&#xff1a; 先進先出&#xff08;FIFO&#xff09;數據處理&#xff1a;當需要按照數據的添加順序進行處理時&#xff0c;可以使用隊列。例如&#xff0c;處理任務隊列、消息隊列等。 示例&#xff…

MySQL慢SQL優化思路

MySQL慢SQL優化思路 具體思路&#xff1a; 1、慢查詢日志記錄慢 SQL 2、explain 分析 SQL 的執行計劃 3、profile 分析執行耗時 4、Optimizer Trace 分析詳情 5、確定問題并采用相應的措施 1、查看慢日志 1.1 使用命令查詢慢日志配置 mysql> show variables like s…

mysql 5.7.34升級到5.7.44修補漏洞

mysql 5.7.34舊版本&#xff0c;漏掃有漏洞&#xff0c;升級到最新版本 舊版本5.7.34在 /home/mysql/mysql中安裝 備份舊版本數據還有目錄 數據庫備份升級 tar -xf mysql-5.7.44-el7-x86_64.tar #覆蓋舊版本數據庫文件 #注意看看文件是否和你起服務的用戶一樣 \cp -r mysql-5…

decomposition-based multi-objective algorithm4SPDPTW

關鍵詞 文章概述 研究背景 多目標選擇性接送和配送問題&#xff08;PDPs&#xff09;&#xff1a;研究涉及多目標選擇性接送和配送問題&#xff0c;這些問題傳統上從單一目標角度進行探討&#xff0c;以尋找最具盈利性的請求集合&#xff0c;同時遵守一系列限制條件。 經濟和…

基于OpenCV+CNN+IOT+微信小程序智能果實采摘指導系統——深度學習算法應用(含python、JS工程源碼)+數據集+模型(五)

目錄 前言總體設計系統整體結構圖系統流程圖 運行環境Python環境TensorFlow 環境Jupyter Notebook環境Pycharm 環境微信開發者工具OneNET云平臺 模塊實現1. 數據預處理2. 創建模型并編譯3. 模型訓練及保存4. 上傳結果5. 小程序開發1&#xff09;查詢圖片2&#xff09;查詢識別結…

?os.path --- 常用路徑操作?

源代碼: Lib/posixpath.py (用于 POSIX) 和 Lib/ntpath.py (用于 Windows)。 此模塊實現了一些有用的路徑名稱相關函數。 要讀取或寫入文件請參見 open()&#xff0c;對于訪問文件系統請參閱 os 模塊。 傳給 path 形參的可以是字符串、字節串或者任何實現了 os.PathLike 協議的…

【收獲】成長之路

目錄 一、前言二、計算機方面三、專業知識方面四、總結 一、前言 四年&#xff0c;對于一個人的成長來說&#xff0c;是一個相當重要的階段。在這段時間里&#xff0c;我經歷了許多挑戰、收獲了許多成就&#xff0c;也在不斷地成長和改變。回首這四年的點點滴滴&#xff0c;我深…

hasattr( )函數的用法

hasattr() 函數用于檢查一個對象是否具有指定的屬性或方法&#xff0c; 它接受兩個參數&#xff1a;對象和屬性名&#xff08;或方法名&#xff09; 函數語法如下&#xff1a; hasattr(object, attribute)參數說明&#xff1a; object&#xff1a;要檢查的對象attribute&…

前端Vue面試題總結

1,Vue組件的生命周期有哪些,它們的執行順序是什么? Vue組件的生命周期包括beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy和destroyed等。它們的執行順序如下:beforeCreate -> created -> beforeMount -> mounted -> be…