jmm--volatile

  1. 指令重排基礎概念
    • 在現代處理器和編譯器為了提高程序執行效率,會對指令進行優化,其中一種優化方式就是指令重排序。在單線程環境下,指令重排序不會影響最終執行結果,因為處理器和編譯器會保證重排序后的執行結果與按照代碼順序執行的結果一致。但在多線程環境下,指令重排序可能會導致程序出現意外的行為。
    • 例如,處理器可能會將一些不依賴于其他指令結果的指令提前執行,以充分利用處理器資源。編譯器也可能對代碼進行優化,改變指令的順序。
  2. volatile 禁止指令重排原理
    • volatile 關鍵字具有禁止指令重排序的語義。Java內存模型(JMM)規定,對 volatile 變量的寫操作,先行發生于后續對這個 volatile 變量的讀操作。這意味著,在 volatile 變量的寫操作之前的所有操作,都必須在 volatile 變量的寫操作之前完成;而 volatile 變量的讀操作,必須在其之后的所有操作之前完成。這種規則確保了 volatile 變量相關的操作順序與代碼順序一致,從而避免了指令重排序帶來的問題。
  3. 代碼示例及執行順序分析
    • 示例1:單例模式中的指令重排問題與 volatile 作用
public class Singleton {// 未使用volatile時可能會出現指令重排問題private static Singleton instance; private Singleton() {}public static Singleton getInstance() {if (instance == null) { // 第一次檢查synchronized (Singleton.class) {if (instance == null) { // 第二次檢查// 這里可能發生指令重排instance = new Singleton(); }}}return instance;}
}

在上述代碼中,instance = new Singleton(); 這行代碼實際上包含了三個步驟:

    1. 分配內存空間給 Singleton 對象。
    1. 初始化 Singleton 對象。
    1. instance 指向分配的內存空間。

在沒有 volatile 修飾的情況下,編譯器和處理器可能會對這三個步驟進行重排序,比如先執行步驟1和3,然后再執行步驟2。假設線程A執行 getInstance() 方法,在步驟1和3執行后,但步驟2還未執行時,線程B進入 getInstance() 方法,此時 instance 已經非空(因為已經指向了分配的內存空間),線程B會直接返回 instance,但此時 instance 還未初始化完成,這就會導致程序出錯。

使用 volatile 修飾 instance 后:

public class Singleton {// 使用volatile防止指令重排private static volatile Singleton instance; private Singleton() {}public static Singleton getInstance() {if (instance == null) { // 第一次檢查synchronized (Singleton.class) {if (instance == null) { // 第二次檢查instance = new Singleton(); }}}return instance;}
}

volatile 關鍵字保證了這三個步驟不會被重排序,一定是按照1 -> 2 -> 3的順序執行,從而確保了 instance 在被其他線程獲取時已經完全初始化。

  • 示例2:簡單變量操作中的指令重排與 volatile
public class VolatileReorderingExample {private static int a = 0;private static volatile boolean flag = false;public static void main(String[] args) {Thread thread1 = new Thread(() -> {a = 1; // 語句1flag = true; // 語句2});Thread thread2 = new Thread(() -> {while (!flag) {// 等待flag變為true}System.out.println(a); // 語句3});thread1.start();thread2.start();}
}

在上述代碼中,如果 flag 沒有被聲明為 volatile,由于指令重排,語句1和語句2的執行順序可能會被改變,即先執行 flag = true; 然后再執行 a = 1;。這樣當線程2執行到 System.out.println(a); 時,a 可能還沒有被賦值為1,輸出結果可能為0。

而當 flag 被聲明為 volatile 后,JMM保證了語句1一定在語句2之前執行,并且語句1的結果對線程2可見。所以當線程2執行 System.out.println(a); 時,a 一定已經被賦值為1,輸出結果為1。

總結來說,volatile 通過JMM的規則,限制了編譯器和處理器對 volatile 變量相關指令的重排序,確保了多線程環境下程序的執行順序符合預期,避免了因指令重排導致的錯誤。

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

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

相關文章

【硬件開發】濾波電容的選擇:原理、計算與多電壓值應用實踐

濾波電容的選擇:原理、計算與多電壓值應用實踐 1. 引言 在現代電子系統中,穩定的電源供應是保證電路可靠運行的基礎。然而,電源線上往往不可避免地存在各種噪聲和紋波,這些干擾可能源自電源本身(如整流后的脈動直流&…

【seismic unix數據生成-unif2】

Seismic Unix簡介 Seismic Unix(SU)是由科羅拉多礦業學院(Colorado School of Mines)開發的開源地震數據處理軟件包,專為地震勘探數據分析和研究設計。它提供了一系列命令行工具,支持從數據加載、處理到可…

【逆向思考 并集查找】P2391 白雪皚皚|省選-

本文涉及知識點 C并集查找 P2391 白雪皚皚 題目背景 “柴門聞犬吠,風雪夜歸人”,冬天,不期而至。千里冰封,萬里雪飄。空中刮起了鴨毛大雪。雪花紛紛,降落人間。 美能量星球(pty 在 spore 上的一個殖民地…

一文講清楚React中setState的使用方法和機制

文章目錄 一文講清楚React中setState的使用方法和機制1. setState是什么2. setState方法詳解2.1 setState參數詳解2.2 setState同步異步問題2.2.1 setState異步更新2.2.2 setState同步更新 一文講清楚React中setState的使用方法和機制 1. setState是什么 React中,…

01_軟件卓越之道:功能性與需求滿足

引言 在軟件的世界里,功能性是產品與用戶之間的第一橋梁。一個軟件即使擁有華麗的界面和極致的性能,如果不能解決用戶的核心需求,也終將被市場淘汰。本文將深入探討如何確保軟件的功能性與用戶需求完美契合。 1. 需求理解:從模糊…

StarRocks × Tableau 連接器完整使用指南 | 高效數據分析從連接開始

一、導語:為什么選擇 StarRocks Tableau 連接器? 在當今數據驅動的商業環境中,企業不僅需要一個能夠處理海量數據的高性能分析數據庫,還需要一個直觀、強大的可視化工具來解讀數據背后的故事。StarRocks 作為新一代極速全場景 MP…

基于 SpringBoot+VueJS 助農生鮮銷售系統設計與實現7000字論文實現

摘要本論文設計并實現了一個基于 SpringBoot 和 VueJS 的助農生鮮銷售系統。系統采用前后端分離架構,前端使用 VueJS 框架實現用戶界面,后端使用 SpringBoot 框架構建服務,通過 MyBatis 實現數據持久化。系統實現了農產品展示、在線購物、訂單…

Pytest 測試發現機制詳解:自動識別測試函數與模塊

概述 在編寫自動化測試時,如何讓 Pytest 自動找到你的測試代碼 是一個非常基礎但重要的問題。Pytest 通過其強大的 測試發現(Test Discovery)機制,能夠自動掃描項目目錄、識別測試模塊和測試函數,從而大大簡化了測試流程。 本文將為你詳細講解 Pytest 的測試發現機制,包…

MySQL 時間日期函數

時間日期類型 MySQL中主要支持以下幾種時間日期類型: DATE - 日期類型 格式:YYYY-MM-DD范圍:1000-01-01 到 9999-12-31示例:2023-05-20 TIME - 時間類型 格式:HH:MM:SS范圍:-838:59:59 到 838:59:59示例&…

408第三季part2 - 計算機網絡 - 物理層

理解 這里有8個波形,每個波形代表一個馬原,一個馬原代表多個比特,這里3個比特 求波特率就直接2W 求比特率就要乘log2V 這塊記兩公式就行,一個下面一個上面 題目 4個相位加4種幅度就是有16種波形 這里無噪聲就是奈奎斯特定理 這…

iOS 集成RN Installing glog (0.3.5)報錯的解決方案

在集成執行RN bundle exec pod install 命令到Installing glog (0.3.5)時報錯,報錯信息如下: Installing glog (0.3.5) [!] /bin/bash -c set -e #!/bin/bash # Copyright (c) Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license …

【進階篇-消息隊列】——MQTT協議如何支持海量的在線IoT設備

目錄 一、什么是IoT二、MQTT 和其他消息隊列的傳輸協議有什么不同三、如何選擇 MQTT 產品四、MQTT 集群如何支持海量在線的 IoT 設備五、總結本文來源:極客時間vip課程筆記 一、什么是IoT IoT,也就是物聯網,物聯網這個詞兒,它的含義還不那么直觀,但你看它的英文:IoT,也就…

Chat Model API

聊天模型API為開發人員提供了將人工智能聊天完成功能集成到應用程序中的能力。它利用預訓練的語言模型,如GPT(生成預訓練轉換器),以自然語言對用戶輸入生成類似人類的響應。 API通常通過向人工智能模型發送提示或部分對話來工作&…

【黑群暉】自組硬件/舊電腦nas改造(三)——使用Jellyfin創建家庭影音庫

一、打開套件中心安裝Jellyfin套件 如果找不到Jellyfin套件,需要手動添加三方套件源: 《群暉NAS必學技能:一鍵解鎖三方套件源,PT下載影音播放全搞定!》 二、配置Jellyfin 訪問http://群暉IP:8096 進入Jellyfin初始化界…

泰山派編譯debian報錯 lb config: unrecognized option ‘--debootstrap-options‘

簡介 最近在編譯泰山派 編譯buildroot系統正常,但是編譯debian時總是報錯說lb 找不到一些參數,如下圖所示,應該當前的版本較低 不支持這些參數,我試了很多方法 升級次版本 但是提示的是最新的,最后經過一番搜索 在官方…

跨境證券交易系統合規升級白皮書:全鏈路微秒風控+開源替代,護航7月程序化交易新規落地

1 行業變革:四重驅動力重塑證券交易系統 當前全球證券行業正處于深刻變革期,跨境金融活動面臨前所未有的機遇與挑戰。今日央行開展的1310億元7天期逆回購操作,以及國家外匯管理局向合格境內機構投資者(QDII)新增發放30.8億美元投資額度等政策…

Node.js核心API(fs篇)

前言:在Node.js生態系統中,文件系統操作是后端開發不可或缺的一部分。fs模塊作為Node.js核心API的重要組成部分,提供了與文件系統交互的能力,涵蓋了從基礎的文件讀寫到復雜的目錄操作等功能。現代JavaScript開發中,處理…

HarmonyOS學習2---Stage模型

1、工程目錄結構 1.1、入口 UIAbility 1.2、入口page 1.3、配置文件 1、配置文件 1)應用級配置文件 --- app.json5 2)模塊級配置文件 --- module.json5 3、oh-package.json5 4、資源文件 1)element目錄 2)media目錄 3&#xff09…

【軟件工程】軟件復刻項目的完整流程指南

軟件復刻項目的完整流程指南 第一章、概述 一、前期準備:明確目標與合規性 1. 法律風險評估 版權排查:確認目標軟件的 UI 設計、代碼、商標是否受保護(如界面元素、核心算法是否申請專利)。規避侵權:避免直接復制 …

淺談Python 中的當前工作目錄與腳本目錄

Python 中的 os.path.exists() 和 __file__ 使用陷阱:工作目錄 ≠ 腳本目錄 在使用 os.path.exists() 或 open() 等函數操作文件路徑時,筆者常常忽略一個關鍵概念:當前運行目錄(Current Working Directory, CWD)并不等…