JavaEE多線程——鎖策略 CAS synchronized優化

目錄

  • 前言
  • 1.鎖策略
    • 1.1 樂觀鎖和悲觀鎖
    • 1.2 重量級鎖和輕量級鎖
    • 1.3 掛起等待鎖和自旋鎖
    • 1.4 公平鎖和非公平鎖
    • 1.5 可重入鎖和不可重入鎖
    • 1.6 讀寫鎖
  • 2.CAS
    • 2.1 CAS的應用
    • 2.2 CAS的ABA問題
  • 3.synchronized優化
    • 3.1鎖升級
    • 3.2鎖消除
    • 3.3鎖粗化
  • 總結

前言

本篇文章主要介紹多線程中鎖策略、CAS和synchronized優化,這三個都是多線程中比較重要的部分。

1.鎖策略

在多線程編程中,鎖是保證線程安全的重要手段。不同的鎖策略適用于不同的場景,了解這些策略有助于我們編寫高效、安全的并發程序。

1.1 樂觀鎖和悲觀鎖

在使用鎖的時候,預測這個鎖遇到沖突的概率
如果預測鎖沖突概率比較高,就稱為“悲觀鎖”,在悲觀鎖中,更傾向于阻塞操作,在訪問數據前就進行加鎖。
如果預測鎖沖突概率比較低,就稱為“樂觀鎖”,在樂觀鎖中,就會嘗試其他方式代替阻塞(例如忙等)。

1.2 重量級鎖和輕量級鎖

重量級鎖表示加鎖的開銷比較大,等待鎖的線程,等待時間可能會比較長。
輕量級鎖表示加鎖的開銷比較小,等待鎖的線程會相對的比較短。

1.3 掛起等待鎖和自旋鎖

這里的兩個鎖是實現層面的。
掛起等待鎖是悲觀鎖/重量級鎖的典型實現,遇到鎖沖突,就會讓線程掛起等待(調度出CPU,等待被CPU喚醒)
自旋鎖則是樂觀鎖/輕量級鎖的典型實現,遇到鎖沖突,不會放棄CPU,而是通過忙等的方式,再次嘗試獲取鎖。

1.4 公平鎖和非公平鎖

公平鎖遵循“先來后到”,按照線程嘗試抓取鎖的順序來進行獲取。
非公平鎖不遵循“先來后到”,而是“概率均等”,每一個嘗試抓取鎖的線程在線程解鎖后都有可能抓取到。

1.5 可重入鎖和不可重入鎖

一個線程針對一個鎖連續加鎖兩次,不觸發死鎖,則是可重入鎖,反之則是不可重入鎖。

1.6 讀寫鎖

讀寫鎖會把加鎖操作分成兩種:讀鎖和寫鎖,在很多場景下,數據讀的次數比寫的次數要頻繁很多,所以把讀寫鎖分開,在讀鎖和讀鎖之間不會產生互斥,讀鎖和寫鎖,寫鎖和寫鎖之間才會產生互斥。這樣降低了很多鎖沖突帶來的性能損失。

2.CAS

CAS全稱compare and swap(比較和交換)
我們假設內存中原數據是V,舊的預期值是A,需要修改的新值是B,我們首先比較V和A是否相等,如果相等,將B寫入V,然后返回一個布爾值。
這里比較特殊的是,這個邏輯是通過一個CPU指令來完成的,
A和B是存儲在兩個寄存器當中,假設寄存器分別為寄存器1,寄存器2,將原數據與寄存器1的值比較,如果相等,就把原數據的值賦值給寄存器2。也就是說,這個操作是原子的,意味著線程安全,不需要加鎖。

2.1 CAS的應用

  1. cas實現原子類
    在標準庫中java.util.concurrent.atomic包里面的類都是基于這種方式來實現的,下面是這個包中的各種類:
    在這里插入圖片描述
    這里典型的一個類就是AtomicInteger,其中getAndIncrement就相當于i++操作,下面看一個例子:
    private static AtomicInteger count = new AtomicInteger(0);public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {count.getAndIncrement(); // 使用原子操作來增加計數}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {count.getAndIncrement(); // 使用原子操作來增加計數}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}

這里使用了AtomicInteger類來實現多線程實現同時自增一個變量,可以看到不進行加鎖的情況下,結果也正確:
在這里插入圖片描述

  1. CAS實現自旋鎖
    使用CAS可以實現自旋鎖,下面看偽代碼:
public class SpinLock {private Thread owner = null;public void lock(){// 通過 CAS 看當前鎖是否被某個線程持有.// 如果這個鎖已經被別的線程持有, 那么就?旋等待.// 如果這個鎖沒有被別的線程持有, 那么就把 owner 設為當前嘗試加鎖的線程.while(!CAS(this.owner, null, Thread.currentThread())){}}public void unlock (){this.owner = null;}
}

循環里判斷鎖是否被占用,如果被占用,就會一直循環,直到不被占用,解鎖狀態。

2.2 CAS的ABA問題

假設有兩個線程T1和T2:
線程T1讀取共享變量的值為A。
然后線程T2將共享變量的值從A修改為B,再修改回A。
最后線程T1再次讀取共享變量的值為A,由于值與最初讀取的A相同,因此CAS操作成功,但實際上共享變量的狀態已經被T2修改過。
這樣T1就無法區分這個變量是否經歷了一系列修改還是始終是A
解決方案:
可以給要修改的值引入版本號,比較當前值和舊值時,也要比較版本號是否符合預期:如果當前版本號和讀到的版本號相同, 則修改數據, 并把版本號 + 1;如果當前版本號?于讀到的版本號. 就操作失敗(認為數據已經被修改過了)。

3.synchronized優化

3.1鎖升級

synchronized具有自適應的特性,會根據情況進行鎖升級,JVM將synchronized分為無鎖、偏向鎖、輕量級鎖、重量級鎖狀態,會依次進行升級。
輕量級鎖和重量級鎖前面已經簡要介紹,這里介紹一下偏向鎖。
偏向鎖并沒有給線程真正加鎖,只是記錄這個鎖屬于哪個線程,如果沒有線程進行競爭這個鎖,偏向鎖狀態就保持,直到最終解鎖;如果遇到其他線程來競爭這個鎖,就在其他線程獲取鎖之前,搶先獲取到這個鎖,也可以讓其他線程阻塞,保證線程安全。

3.2鎖消除

有些代碼中寫了加鎖,但是如果JVM執行時發現不需要加鎖,就會自動把鎖去掉。比如StringBuffer帶有synchronized鎖,如果在單線程情況下使用,JVM和編譯器則會進行判斷,將鎖”消除“。

3.3鎖粗化

這里涉及的是鎖的粒度
加鎖和范圍中代碼越多,鎖的粒度越粗。
如果有一系列獨立的加鎖、解鎖操作,JVM可以回將他們合并成一個更大的鎖范圍,只加鎖解鎖一次,這樣減少了系統的調用開銷,同時也減少了鎖競爭。

總結

本篇文章介紹了鎖策略,CAS以及synchronized的優化,在后面會對synchronized進行總結。

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

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

相關文章

Windows符號鏈接解決vscode和pycharm占用C盤空間太大的問題

Windows符號鏈接解決vscode和pycharm占用C盤空間太大的問題 參考文章&#xff1a;Windows符號鏈接 1、找到vscode和pycharm在C盤的緩存文件夾。 C:\Users\用戶名\AppData\Roaming\Code C:\Users\用戶名\.vscode\extensionsC:\Users\用戶名\AppData\Local\JetBrains C:\Users…

賦能家庭、行業與工業場景,智微智能新一代Twin Lake 全棧智能終端發布

在數字化浪潮席卷全球的今天&#xff0c;智能終端已成為連接物理世界與數字世界的核心樞紐。智微智能基于Intel Twin Lake平臺&#xff0c;推出覆蓋家庭/行業應用及工業物聯網的全場景產品矩陣&#xff0c;為不同場景下的用戶提供高效、可靠的產品和解決方案。Intel Twin Lake架…

復習筆記 31

前言 好好復習。今天距離考研初試還剩一百六十一天。我的時間其實沒剩多少了呀。我得好好加油。 歸并排序 #include<algorithm> #include<iostream>using namespace std;const int N 100010; int n; int a[N], tmp[N];void merge ( int a[], int l, int r ) {if (…

el-tree 懶加載 loadNode

el-tree 是 Element UI 提供的樹形組件&#xff0c;其懶加載功能通過 loadNode 方法實現&#xff0c;可以在用戶展開節點時動態加載子節點數據&#xff0c;避免一次性加載大量數據。下面介紹 loadNode 的具體用法和示例。基本用法loadNode 是 el-tree 的一個重要屬性&#xff0…

【機器學習入門巨詳細】(研0版)二創OPEN MLSYS

自學機器學習&#xff0c;從入門到精通導論機器學習的基本框架設計目標機器學習框架基本組成原理機器學習生態機器學習工作流環境配置數據處理模型定義損失函數和優化器訓練及保存模型測試及驗證模型定義深度神經網絡以層為核心定義神經網絡神經網絡層實現原理自定義神經網絡層…

Excel 轉 JSON by WTSolutions API 文檔

Excel 轉 JSON by WTSolutions API 文檔 簡介 Excel 轉 JSON API 提供了一種簡單的方式將 Excel 和 CSV 數據轉換為 JSON 格式。該 API 接受制表符分隔或逗號分隔的文本數據&#xff0c;并返回結構化的 JSON。 接口端點 POST https://mcp.wtsolutions.cn/excel-to-json-api 請求…

git版本發布

cvs和svn都是集中式版本控制系統,而git是分布式版本控制系統。 1、集中式版本控制系統必須聯網才能工作&#xff0c;如果在局域網內還好&#xff0c;帶寬夠大&#xff0c;速度夠快&#xff0c;可如果在互聯網上&#xff0c;遇到網速慢的話&#xff0c;呵呵。分布式版本控制系統…

138-EMD-KPCA-CPO-CNN-BiGRU-Attention模型!

138-EMD-KPCA-CPO-CNN-BiGRU-Attention基于經驗模態分解和核主成分分析的長短期記憶網絡改進多維時間序列預測MATLAB代碼&#xff01;其中&#xff08;含CPO-CNN-BiGRU-attention、EMD-CPO-CNN-BiGRU-Attention、EMD-KPCA-CPO-CNN-BiGRU-Attention三個模型的對比&#xff09; 可…

系統思考:多元勝過能力

系統思考&#xff1a;從整體出發&#xff0c;打破瓶頸&#xff0c;擁抱多元 我們是否曾經陷入過這樣的困境&#xff1f; 1、專注能力提升&#xff0c;卻無法突破瓶頸&#xff1a;我和團隊日復一日地努力提升個人能力&#xff0c;投入無數時間和精力&#xff0c;但始終無法打破現…

qt樣式整合持續更新中(實測有效的)

// 僅顯示上邊框 一般可以作為直線使用 border-top: 2px solid black; //畫虛線 border-bottom: 2px dashed white; //單個圓角 border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; //透明背景 background:rgba(0,0,0,0); //設置字體 font:15pt; //給button設置…

[java][springboot]@PostConstruct的介紹和用法

在 Spring Boot&#xff08;以及整個 Spring Framework&#xff09;中&#xff0c;PostConstruct 是一個非常常用的注解&#xff0c;用于在 依賴注入完成后 執行一些初始化操作。import jakarta.annotation.PostConstruct; import org.springframework.stereotype.Component;Co…

Leaflet面試題及答案(41-60)

查看本專欄目錄 文章目錄 ?? 面試問題及答案(41-60)41. 如何判斷某個點是否在地圖可視區域內?42. 如何動態更新 Marker 位置?43. 如何清除地圖上的所有圖層?44. 如何保存地圖截圖?45. 如何檢測瀏覽器是否支持觸摸?46. Leaflet 是否支持 TypeScript?47. 如何修改默認圖…

Redis事件機制

Redis 采用事件驅動機制來處理大量的網絡IO。它并沒有使用 libevent 或者 libev 這樣的成熟開源方案&#xff0c;而是自己實現一個非常簡潔的事件驅動庫 ae_event。事件機制Redis中的事件驅動庫只關注網絡IO&#xff0c;以及定時器。該事件庫處理下面兩類事件&#xff1a;文件事…

Linux基礎開發工具

目錄 1.寫在前面 2.權限 3.file命令 4.基礎開發工具 1.軟件包管理器 5.編輯器vim 1.寫在前面 我們在上一講解中講解了權限是人事物屬性&#xff0c;還知道了擁有者所屬組其他人這三個概念&#xff0c;知道了33一組&#xff0c;rwx分別代表什么。那么下面我們繼續進行權限…

ICCV2025 特征點檢測 圖像匹配 RIPE

目測對剛性物體效果比較好代碼&#xff1a;https://github.com/fraunhoferhhi/RIPE 論文&#xff1a;https://arxiv.org/abs/2507.04839import cv2 import kornia.feature as KF import kornia.geometry as KG import matplotlib.pyplot as plt import numpy as np import torc…

Ubuntu22.0.4安裝PaddleNLP

Ubuntu22.0.4安裝PaddleNLP環境說明安裝底層框架Paddle安裝PddleNLP1. pip安裝2. 驗證安裝3. 最后問題集錦環境說明 1. miniconda 25.5.1 2. python 3.12.11 3. pip 25.1 4. nvidia 570.144 5. cuda 12.8**注意&#xff1a;**安裝過程可能遇到的一些問題&#xff0c;參考末尾的…

【HTTP服務端】Cookie?Session?Token?

文章目錄cookie與sessiontoken什么是JWT&#xff1f;JWT的組成結構1. Header&#xff08;頭部&#xff09;2. Payload&#xff08;負載&#xff09;3. Signature&#xff08;簽名&#xff09;JWT工作原理JWT的特點安全注意事項cookie與session cookie有哪些屬性 鍵值對&#xf…

安裝Git

Git安裝避坑指南技術 操作系統選擇與準備 Windows用戶需注意系統版本兼容性&#xff0c;建議使用Windows 10及以上版本 Mac用戶需檢查是否安裝Xcode Command Line Tools Linux用戶需區分apt/yum等包管理器命令差異 安裝包下載注意事項 從官方渠道&#xff08;git-scm.com&a…

UDP服務器的優缺點都包含哪些?

UDP協議不需要像TCP協議那樣進行復雜的連接建立與拆除過程&#xff0c;在進行傳輸數據信息的過程中&#xff0c;應用層將數據交給UDP層&#xff0c;UDP層直接加上首部就發往網絡層&#xff0c;極大地減少了處理時間和資源消耗。例如在一些簡單的網絡監控程序中&#xff0c;只是…

sqli-labs靶場通關筆記:第7-8關 布爾盲注

第七關1.審題這里判斷出是))閉合&#xff0c;但是頁面只有正確和錯誤的回顯狀態&#xff0c;報錯的回顯也是固定的&#xff0c;沒有顯示報錯具體信息。這關使用的方法是布爾盲注。為什么叫布爾盲注&#xff1f;因為它返回的結果只有true和false 兩個值&#xff0c;攻擊者需要通…