并發基礎—三大問題:可見性、原子性、有序性

文章目錄

  • 可見性
  • 原子性
  • 有序性(指令重排)
    • 經典的指令重排案例:單例模式的雙重檢查鎖
    • volatile和synchronize都可以保證有序性
    • 并發壓測工具Jcstress證明指令重排會在多線程下出現問題(了解)
    • CPU緩存分為三個級別:L1、L2、L3
    • 寄存器
    • 緩存和寄存器的區別
      • JMM(java memory modle)

可見性

原子性

并發編程時,當一個線程對共享變量的修改操作進行到一半時,另一個線程也可能來操作共享變量,這時就會干擾前一個線程的操作,這也就是原子性問題。

public class AtomicDemo {private static int num = 0;public static void main(String[] args) {List<Thread> list = new ArrayList<>();for (int i = 0; i < 5; i++) {Thread thread = new Thread(() -> {for (int j = 0; j < 1000; j++) {num++;}});list.add(thread);thread.start();}list.forEach(e -> {try {e.join();} catch (InterruptedException ex) {ex.printStackTrace();}});System.out.println(num);}
}

上面代碼的運行結果不一定是5000,原因分析如下:
i++編譯后對應的JVM指令實際有4條,當只執行了部分操作時,另一個線程同時操作i變量,就會出現原子性問題
在這里插入圖片描述

有序性(指令重排)

指令重排:為了保證程序的執行效率,在不影響正確性的前提下,編譯器和CPU會對程序中代碼進行優化,即指令重排序

  • 指令重排必須保證單線程情況下程序的運行結果是正確的
  • 指令重排在多線程下可能會影響程序運行結果的正確性。

經典的指令重排案例:單例模式的雙重檢查鎖

volatile和synchronize都可以保證有序性

  • synchronize:保證了只有一個線程在操作同步代碼塊內的代碼,而指令重排在單線程的情況下運行結果是正確的

并發壓測工具Jcstress證明指令重排會在多線程下出現問題(了解)

<dependency><groupId>org.openjdk.jcstress</groupId><artifactId>jcstress-core</artifactId><version>0.7</version><scope>test</scope>
</dependency>
/**
* 需求:測試指令重排導致程序結果異常情況
* 方法test2中,有可能 flag=true先執行,而num=2后執行,位置交換導致出現方法test1結果r.r1=0
*/
@JCStressTest
//表示對輸出結果的處理  Expect.ACCEPTABLE 可以接收的結果
@Outcome(id = {"1", "4"}, expect = Expect.ACCEPTABLE, desc = "ok")
//Expect.ACCEPTABLE_INTERESTING 表示可以接收,并感興趣的結果
@Outcome(id = "0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "danger")
@State
public class jcstress {int num = 0;boolean flag = false;//線程1執行的代碼@Actorpublic void test1(I_Result r) {if (flag) {r.r1 = num + num;} else {r.r1 = 1;}}//線程2執行的代碼@Actorpublic void test2(I_Result r) {num = 2;flag = true;}
}

在這里插入圖片描述

CPU緩存分為三個級別:L1、L2、L3

CPU的運算速度和內存的訪問速度相差比較大,導致CPU每次操作內存都需要耗費大量的等待時間,于是CPU和內存直接增加了緩存設計。

(1)L1(一級緩存)是最接近CPU的,三個緩存中它容量最小,速度最快,每個物理內核上都有個一級緩存L1
(2)L2(二級緩存)速度比L1慢,比L3快,一般情況下每個物理核上都有一個獨立的L2
(3)L3(三級緩存)是三個緩存中最大的,同時也是速度最慢的,同一個CPU插槽上的核共用一個三級緩存

寄存器

CPU和一級緩存之間還有寄存器,CPU經常使用同一內存地址的某數據時 ,為減少頻繁讀取的消耗,就會把該數據存儲到寄存器。

緩存和寄存器的區別

(1)緩存是把CPU需要的數據提前緩存起來,減少讀取的消耗,但不一定是經常使用的
(2)寄存器是把CPU經常使用的同一內存地址的數據緩存起來,減少讀取消耗
在這里插入圖片描述
在這里插入圖片描述

JMM(java memory modle)

java內存模型和java內存結構不是一回事,java內存模型用于多線程讀寫共享數據時,保證共享數據的可見性、有序性、原子性,主要是通過synchronize、volatile兩個關鍵字來實現

(1)主內存:主內存是所有線程都能訪問,所有共享變量都存儲在主內存—方法區和堆
(2)工作內存:每個線程都有自己的工作內存,只存儲該線程需要用到的共享變量的副本,線程對變量的所有操作都是工作內存完成的,而不是直接讀寫主內存的變量,不同線程之間也不能相互訪問工作內存中的變量。
(3)jMM內存模型和硬件內存不是一回事,它是一個抽象的概念,不管是工作內存的數據還是主內存的數據,即可能存儲到內存,也可能存到CPU的三級緩存或者寄存器中。
在這里插入圖片描述

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

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

相關文章

PyTorch 入門學習

目錄 PyTorch 定義 核心作用 應用場景 Pytorch 基本語法 1. 張量的創建 2. 張量的類型轉換 3. 張量數值計算 4. 張量運算函數 5. 張量索引操作 6. 張量形狀操作 7. 張量拼接操作 8. 自動微分模塊 9. 案例-線性回歸案例 PyTorch 定義 PyTorch 是一個基于 Python 深…

Hive SQL 精進系列:REGEXP_REPLACE 函數的用法

目錄 一、引言二、REGEXP_REPLACE 函數基礎2.1 基本語法參數詳解2.2 簡單示例 三、REGEXP_REPLACE 函數的應用場景3.1 去除特殊字符3.2 統一字符串格式 四、REGEXP_REPLACE 與 REPLACE 函數的對比4.1 功能差異4.2 適用場景 五、REGEXP_REPLACE 與 REGEXP 函數的對比5.1 功能差異…

從0開始搭建微服務架構特別篇SpringCloud網關聚合knife4j

前言&#xff1a;總所周知項目開發接口測試需要knife4j&#xff0c;但是&#xff0c;微服務架構中微服務很多&#xff0c;模塊地址很多&#xff0c;需要統一管理api測試&#xff0c;就需要聚合在網關統一調用&#xff0c;本章&#xff0c;就說明如何通過網關聚合使用knife4j。 …

Spring Cloud 中的服務注冊與發現: Eureka詳解

1. 背景 1.1 問題描述 我們如果通過 RestTamplate 進行遠程調用時&#xff0c;URL 是寫死的&#xff0c;例如&#xff1a; String url "http://127.0.0.1:9090/product/" orderInfo.getProductId(); 當機器更換或者新增機器時&#xff0c;這個 URL 就需要相應地變…

網頁制作15-Javascipt時間特效の記錄網頁停留時間

01效果圖&#xff1a; 02運用&#xff1a; window.setTimeout&#xff08;&#xff09;刷新function&#xff08;&#xff09;函數document.forms&#xff08;&#xff09;&#xff1a;表單if條件語句window.alert&#xff08;&#xff09;窗口警示 03、操作代碼&#xff1a;…

【Rust基礎】排序和分組

排序 簡單排序 整數排序 #[test] fn test_sort(){let mut list vec![1, 5, 3, 2, 4];list.sort(); //?assert_eq!(list, vec![1, 2, 3, 4, 5]); }小數排序 #[test] fn test_sort(){let mut list vec![1, 5, 3, 2, 4];//? 不能直接使用sort&#xff0c;因為f32和f64未實現O…

C++ std::list超詳細指南:基礎實踐(手搓list)

目錄 一.核心特性 1.雙向循環鏈表結構 2.頭文件&#xff1a;#include 3.時間復雜度 4.內存特性 二.構造函數 三.list iterator的使用 1.學習list iterator之前我們要知道iterator的區分 ?編輯 2.begin()end() 3.rbegin()rend() 四.list關鍵接口 1.empty() 2. size…

996引擎 - 紅點系統

996引擎 - 紅點系統 總結NPC 紅點(TXT紅點)Lua 紅點1. Red_Point.lua2. UI_Ex.lua參考資料以下內容是在三端 lua 環境下測試的 總結 紅點系統分幾個部分組成。 M2中設置變量推送。 配置紅點表。 Envir\Data\cfg_redpoint.xls 2.1. UI元素中找到ID填寫 ids 列。 主界面掛載…

C語言——變量與常量

C語言中的變量與常量&#xff1a;簡潔易懂的指南 在C語言編程中&#xff0c;變量和常量是最基本的概念之一。理解它們的區別和使用方法對于編寫高效、可維護的代碼至關重要。本文將詳細介紹C語言中的變量和常量&#xff0c;并通過圖表和代碼示例幫助你更好地理解。 目錄 什么…

PySide(PyQt),使用types.MethodType動態定義事件

以PySide(PyQt)的圖片項為例&#xff0c;比如一個視窗的場景底圖是一個QGraphicsPixmapItem&#xff0c;需要修改它的鼠標滾輪事件&#xff0c;以實現鼠標滾輪縮放顯示的功能。為了達到這個目的&#xff0c;可以重新定義一個QGraphicsPixmapItem類&#xff0c;并重寫它的wheelE…

K8S學習之基礎三十一:k8s中RBAC 的核心概念

Kubernetes (k8s) 中的 RBAC&#xff08;Role-Based Access Control&#xff0c;基于角色的訪問控制&#xff09;是一種用于管理用戶和服務賬戶對集群資源訪問權限的機制。RBAC 允許管理員通過定義角色&#xff08;Role&#xff09;和角色綁定&#xff08;RoleBinding&#xff…

【eNSP實戰】三層交換機使用ACL實現網絡安全

拓圖 要求&#xff1a; vlan1可以訪問Internetvlan2和vlan3不能訪問Internet和vlan1vlan2和vlan3之間可以互相訪問PC配置如圖所示&#xff0c;這里不展示 LSW1接口vlan配置 vlan batch 10 20 30 # interface Vlanif1ip address 192.168.40.2 255.255.255.0 # interface Vla…

軟考系統架構師 — 1 考點分析

目錄 1 考點總結 1 考點總結 章節 內容 真題考察 緒論 1. 緒論 不考 計算機相關知識 2. 計算機系統基礎知識&#xff0c;新增計算機硬件、嵌入式、計算機語言、系統工程 對應計算機組成結構、操作系統、數據庫、計算機網絡、多媒體等知識點&#xff0c;整體分值在 10 …

在Eclipse 中使用 MyBatis 進行開發,通常需要以下步驟:

在Eclipse 中使用 MyBatis 進行開發&#xff0c;通常需要以下步驟&#xff1a; 1. 創建 Maven 項目 首先&#xff0c;在 Eclipse 中創建一個 Maven 項目。如果你還沒有安裝 Maven 插件&#xff0c;可以通過 Eclipse Marketplace 安裝 Maven 插件。 打開 Eclipse&#xff0c;選…

錯誤記錄: git 無法連接到github

錯誤記錄: git 無法連接到github 今天, 新建了一個github倉庫, 但從本地怎么都push不上去.并報錯 gitgithub.com: Permission denied (publickey). fatal: Could not read from remote repository.Please make sure you have the correct access rights and the repository e…

k8s 配置兩個deployment主機級別互斥部署

在 Kubernetes 中&#xff0c;要實現兩個 Deployment 的 Pod 在主機級別互斥部署&#xff0c;可以使用 podAntiAffinity 配置。通過設置 podAntiAffinity&#xff0c;可以確保兩個 Deployment 的 Pod 不會被調度到同一節點上。 實現步驟 定義 Deployment&#xff1a; 為每個…

Unity中WolrdSpace下的UI展示在上層

一、問題描述 Unity 中 Canvas使用World Space布局的UI&#xff0c;想讓它不被3d物體遮擋&#xff0c;始終顯示在上層。 二、解決方案 使用shader解決 在 UI 的材質中禁用深度測試&#xff08;ZTest&#xff09;&#xff0c;強制 UI 始終渲染在最上層。 Shader "Custo…

五子棋小游戲-簡單開發版

一、需求分析 開發一個基于 Pygame 庫的五子棋小游戲&#xff0c;允許兩名玩家在棋盤上輪流落子&#xff0c;當有一方達成五子連珠時游戲結束&#xff0c;顯示獲勝信息&#xff0c;并提供退出游戲和重新開始游戲的操作選項。 1.棋盤顯示 &#xff1a; 顯示一個 15x15 的五子棋…

基于C#的以太網通訊實現:TcpClient異步通訊詳解

基于C#的以太網通訊實現&#xff1a;TcpClient異步通訊詳解 在現代工業控制和物聯網應用中&#xff0c;以太網通訊是一種常見的數據傳輸方式。本文將介紹如何使用C#實現基于TCP協議的以太網通訊&#xff0c;并通過異步編程提高通訊效率。我們將使用TcpClient類來實現客戶端與服…

小秋的矩陣

0小秋的矩陣 - 藍橋云課 問題描述 給你一個 n 行 m 列只包含 0 和 1 的矩陣&#xff0c;求它的所有子矩陣中&#xff0c;是方陣而且恰好包含 k 個 0 的數量。 方陣是行數和列數相等的矩陣。 子矩陣是從一個矩陣當中選取某些行和某些列交叉位置所組成的新矩陣&#xff08;保…