Java【多線程】(8)CAS與JUC組件


目錄

1.前言

2.正文

2.1CAS概念

2.2CAS兩種用途

2.2.1實現原子類

2.2.2實現自旋鎖

2.3缺陷:ABA問題

2.4JUC組件

2.4.1Callable接口

2.4.2ReentrantLock(與synchronized對比)

2.4.3Semaphore信號量

2.4.4CountDownLatch

3.小結


1.前言

哈嘍大家好吖,不知不覺多線程這一塊大骨頭終于快要啃完了,今天給大家分享的是CAS以及JUC相關組件,那么廢話不多說讓我們開始吧。

2.正文

2.1CAS概念

核心思想:無所并發控制

CAS(Compare And Swap)是一種基于樂觀鎖的無鎖并發控制技術。其核心邏輯可以概括為:“我認為當前值應該是A,如果是,則更新為B;否則放棄或重試”。整個過程由硬件保證原子性,無需傳統鎖機制。


通俗來說
假設你和同事協同編輯一份共享文檔,每次保存時系統會檢查:

  1. 當前內容是否和你打開時的版本一致(預期值比對)。

  2. 如果一致,允許保存;否則提示“內容已變更,請重新編輯”。
    這個過程就是CAS的核心思想——樂觀鎖:先操作,沖突時重試,而非直接加鎖阻塞。


CAS操作的偽代碼可以拆解為以下步驟,幫助理解其原子性本質:

// 偽代碼:CAS操作的邏輯分解
public boolean compareAndSwap(MemoryAddress addr, int expectedValue, int newValue) {// 1. 讀取內存當前值int currentValue = *addr; // 2. 比較當前值與預期值if (currentValue != expectedValue) {return false; // 值已被其他線程修改,操作失敗}// 3. 若值未變,執行原子性更新*addr = newValue;return true;
}

2.2CAS兩種用途

2.2.1實現原子類

針對原子類,++--這樣的操作是原子的,基于CAS實現,不涉及到加鎖。


傳統實現:

private int count = 0;  
public synchronized void increment() {  count++;  
}  

進階實現: (使用Java提供的原子類)

AtomicInteger count = new AtomicInteger(0);  
public void increment() {  int oldValue, newValue;  do {  oldValue = count.get();  newValue = oldValue + 1;  } while (!count.compareAndSet(oldValue, newValue)); // CAS自旋  
}  

2.2.2實現自旋鎖

先回顧一個上篇文章的概念:自旋鎖是線程通過循環(自旋)不斷嘗試獲取鎖,而非立即阻塞。適用于鎖持有時間極短的場景。

代碼實現:

public class CASSpinLock {  private AtomicBoolean locked = new AtomicBoolean(false);  // 獲取鎖  public void lock() {  while (!locked.compareAndSet(false, true)) {  // 自旋:直到成功將locked從false改為true  }  }  // 釋放鎖  public void unlock() {  locked.set(false);  }  
}  
  • 線程競爭不激烈時(如短任務),自旋鎖比系統鎖(如synchronized)更高效。

  • 缺點:長時間自旋會浪費CPU資源(需根據場景權衡)。

2.3缺陷:ABA問題

ABA問題場景

  1. 線程1讀取變量值為A

  2. 線程2將值改為B,隨后又改回A

  3. 線程1執行CAS操作,發現當前值仍是A,誤認為未被修改過,操作成功。


通俗理解:

  • 你看到自己的水杯是滿的(A),去接水時離開了一會兒。

  • 期間別人喝光水(A→B)又倒滿(B→A)。

  • 你回來后以為水沒被喝過,直接喝下(可能喝到別人的水!)。

這里在實際場景中就是非常嚴重的線程安全的問題了。

解決方案:?

?

1. 版本號標記(AtomicStampedReference)
為值附加一個版本號(類似“修改次數”),CAS時同時校驗值和版本號。

AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);  // 線程1讀取值和版本號  
int stamp = ref.getStamp();  
String oldValue = ref.getReference();  // 線程2修改值并更新版本號  
ref.compareAndSet("A", "B", stamp, stamp + 1);  
ref.compareAndSet("B", "A", stamp + 1, stamp + 2);  // 線程1嘗試修改:雖然值還是A,但版本號已變,操作失敗!  
boolean success = ref.compareAndSet(oldValue, "C", stamp, stamp + 1);  

2. 狀態標記(AtomicMarkableReference)
用布爾值標記是否被修改過(簡化版版本號)。

2.4JUC組件

2.4.1Callable接口

官方解析:Callable (Java SE 17 & JDK 17)

Callable?是 Java 并發包(JUC)中定義的接口,類似于?Runnable,但允許線程執行任務后返回結果,并可以拋出異常。

與?Runnable?的區別:

  • Runnable?的?run()?沒有返回值,Callable?的?call()?可以返回泛型結果。

  • call()?可以拋出受檢異常,run()?不能。

具體案例(異步運算1加到100):

Callable<Integer> task = () -> {int sum = 0;for (int i = 1; i <= 100; i++) sum += i;return sum;
};
FutureTask<Integer> futureTask = new FutureTask<>(task);
new Thread(futureTask).start();// 主線程獲取結果
System.out.println("計算結果:" + futureTask.get()); // 輸出 5050

通過?FutureTask?包裝?Callable?任務,啟動線程執行后,主線程通過?futureTask.get()?等待結果返回,類似“異步任務+回調”模式。?

2.4.2ReentrantLock(與synchronized對比)

官方解析:ReentrantLock (Java SE 17 & JDK 17)

ReentrantLock?是 JUC 提供的顯式鎖,支持可重入性、可中斷鎖、公平鎖等特性。

特性synchronizedReentrantLock
鎖獲取方式隱式(JVM 管理)顯式(代碼手動加鎖/解鎖)
可中斷不支持支持?lockInterruptibly()
公平鎖不支持支持(構造函數指定)
條件變量(Condition)支持(newCondition()

?案例:

class BankAccount {private final ReentrantLock lock = new ReentrantLock();private int balance = 100;void transfer(BankAccount target, int amount) {lock.lock();try {if (this.balance >= amount) {this.balance -= amount;target.balance += amount;}} finally {lock.unlock(); // 必須手動釋放鎖}}
}

synchronized?的等價實現是在方法簽名加?synchronized?關鍵字,但?ReentrantLock?更靈活:

  • 可設置超時時間(tryLock(1, TimeUnit.SECONDS))。

  • 公平鎖減少線程饑餓問題。

2.4.3Semaphore信號量

官方解析:Semaphore (Java SE 17 & JDK 17)

Semaphore?用于控制同時訪問某個資源的線程數量,類似“許可證發放”。

核心方法

  • acquire():獲取許可證(若無可用則阻塞)。

  • release():釋放許可證。

?案例:(模擬停車場)

Semaphore semaphore = new Semaphore(3); // 3 個許可證Runnable parkAction = () -> {try {semaphore.acquire(); // 獲取車位System.out.println(Thread.currentThread().getName() + " 停入車位");Thread.sleep(2000); // 停車 2 秒} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release(); // 釋放車位System.out.println(Thread.currentThread().getName() + " 離開車位");}
};// 啟動 5 輛車嘗試停車
for (int i = 0; i < 5; i++) {new Thread(parkAction).start();
}

2.4.4CountDownLatch

官方解析:CountDownLatch (Java SE 17 & JDK 17)

CountDownLatch?是一個同步工具,允許一個或多個線程等待其他線程完成操作。

核心方法:

  • countDown():計數器減 1。

  • await():阻塞直到計數器歸零。?

public static void main(String[] args) {CountDownLatch latch = new CountDownLatch(3); // 需要等待 3 個任務// 資源加載任務Runnable loadTask = () -> {try {Thread.sleep((long) (Math.random() * 2000));System.out.println(Thread.currentThread().getName() + " 加載完成");latch.countDown();} catch (InterruptedException e) {e.printStackTrace();}};// 啟動 3 個資源加載線程new Thread(loadTask, "地圖").start();new Thread(loadTask, "音效").start();new Thread(loadTask, "UI").start();// 主線程等待所有資源加載完成try {latch.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("所有資源加載完成,開始游戲!");}

3.小結

今天的分享到這里就結束了,喜歡的小伙伴點點贊點點關注,你的支持就是對我最大的鼓勵,大家加油!

?

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

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

相關文章

【Docker】離線安裝Docker

背景 離線安裝Docker的必要性&#xff0c;第一&#xff0c;在目前數據安全升級的情況下&#xff0c;很多外網已經基本不好訪問了。第二&#xff0c;如果公司有對外部署的需求&#xff0c;那么難免會存在對方只有內網的情況&#xff0c;那么我們就要做到學會離線安裝。 下載安…

MecAgent Copilot:機械設計師的AI助手,開啟“氛圍建模”新時代

MecAgent Copilot作為機械設計師的AI助手,正通過多項核心技術推動機械設計進入“氛圍建模”新時代。以下從功能特性、技術支撐和應用場景三方面解析其創新價值: 一、核心功能特性 ??智能草圖生成與參數化建模?? 支持自然語言輸入生成設計草圖和3D模型,如輸入“剖面透視…

MCU屏和RGB屏

一、MCU屏 MCU屏?&#xff1a;全稱為單片機控制屏&#xff08;Microcontroller Unit Screen&#xff09;&#xff0c;在顯示屏背后集成了單片機控制器&#xff0c;因此&#xff0c;MCU屏里面有專用的驅動芯片。驅動芯片如&#xff1a;ILI9488、ILI9341、SSD1963等。驅動芯片里…

7.5 使用MobileNet v3進行圖像的區分

MobileNet v3是Google在2019年提出的輕量級卷積神經網絡結構,旨在提高在移動設備上的速度和準確性,廣泛的用于輕量級網絡。 MobileNet v3-Small的網絡結構如下,它的輸入是224x224的3通道彩色圖片。 使用過程如下: 1.創建模型、修改最終分類數量 #1.創建mobilenet_v3_small…

構建面向大模型訓練與部署的一體化架構:從文檔解析到智能調度

作者&#xff1a;汪玉珠&#xff5c;算法架構師 標簽&#xff1a;大模型訓練、數據集構建、GRPO、自監督聚類、指令調度系統、Qwen、LLaMA3 &#x1f9ed; 背景與挑戰 隨著 Qwen、LLaMA3 等開源大模型不斷進化&#xff0c;行業逐漸從“能跑通”邁向“如何高效訓練與部署”的階…

PostgreSQL技術大講堂 - 第86講:數據安全之--data_checksums天使與魔鬼

PostgreSQL技術大講堂 - 第86講&#xff0c;主題&#xff1a;數據安全之--data_checksums天使與魔鬼 1、data_checksums特性 2、避開DML規則&#xff0c;嫁接非法數據并合法化 3、避開約束規則&#xff0c;嫁接非法數據到表中 4、避開數據檢查&#xff0c;讀取壞塊中的數據…

【機器學習】機器學習筆記

1 機器學習定義 計算機程序從經驗E中學習&#xff0c;解決某一任務T&#xff0c;進行某一性能P&#xff0c;通過P測定在T上的表現因經驗E而提高。 eg&#xff1a;跳棋程序 E&#xff1a; 程序自身下的上萬盤棋局 T&#xff1a; 下跳棋 P&#xff1a; 與新對手下跳棋時贏的概率…

Ubuntu20.04 設置開機自啟

參考&#xff1a; Ubuntu20.04 設置開機自啟_ubuntu進bos系統-CSDN博客

數據庫中存儲過程的流程語句講解

一、流程語句講解 二、總結 一、流程語句講解 1.1 if語句講解 語法&#xff1a; IF condition THENstatements; ELSEIF condition THENstatements; ELSEstatements; END IF; 題目示例&#xff1a; # 判斷成績等級 # 輸入學生的編號,取出學生的第一門課&#xff0c;然后判斷…

kubernetes》》k8s》》ConfigMap 、Secret

configmap官網 ConfigMap是一種 API 對象&#xff0c;使用時&#xff0c; Pods 可以將其用作環境變量、命令行參數或者存儲卷中的配置文件。ConfigMap將配置和Pod解耦&#xff0c;更易于配置文件的更改和管理。ConfigMap 并不提供保密或者加密功能。 如果你想存儲的數據是機密的…

git在IDEA中使用技巧

git在IDEA中使用技巧 merge和rebase 參考&#xff1a;IDEA小技巧-Git的使用 git回滾、強推、代碼找回 參考&#xff1a;https://www.bilibili.com/video/BV1Wa411a7Ek?spm_id_from333.788.videopod.sections&vd_source2f73252e51731cad48853e9c70337d8e cherry pick …

Spring 事務失效的原因及解決方案全解析,來復習了

Spring 事務失效是指在使用 Spring 聲明式事務管理時&#xff0c;預期的事務行為&#xff08;如事務的開啟、提交、回滾等&#xff09;未按預期執行&#xff0c;導致數據操作未滿足 ACID 特性&#xff08;原子性、一致性、隔離性、持久性&#xff09;&#xff0c;從而引發數據不…

「出海匠」借助CloudPilot AI實現AWS降本60%,支撐AI電商高速增長

&#x1f50e;公司簡介 「出海匠」&#xff08;chuhaijiang.com&#xff09;是「數繪星云」公司打造的社交內容電商服務平臺&#xff0c;專注于為跨境生態參與者提供數據支持與智能化工作流。平臺基于大數據與 AI 技術&#xff0c;幫助商家精準分析市場趨勢、優化運營策略&…

python每日一練

題目一 輸入10個整數,輸出其中不同的數,即如果一個數出現了多次,只輸出一次(要求按照每一個不同的數第一次出現的順序輸出)。 解題 錯誤題解 a list(map(int,input().split())) b [] b.append(a[i]) for i in range(2,11):if a[i] not in b:b.append(a[i]) print(b)但是會…

Docker實戰:從零構建高可用的MySQL主從集群與Redis集群

在分布式系統架構中&#xff0c;數據庫集群是保障數據高可用和性能的關鍵組件。本文將通過Docker技術&#xff0c;手把手教你搭建MySQL主從集群和Redis Cluster&#xff0c;并分享獨創的優化技巧與運維實戰經驗。 一、為什么選擇Docker部署集群&#xff1f; 傳統數據庫集群搭…

STM32電機庫 電機控制特性

ST MC FW庫提供FOC和六步法兩種電機控制方式。這使得它能夠驅動永磁同步電機 (PMSM) 和無刷直流電機 (BLDC)。FOC 更適合 PMSM,而六步法更適合 BLDC 電機。該固件可以驅動內嵌式PMSM 和標貼式PMSM。 ST Motor Control 固件庫提供以下功能: FOC SVPWM 生成: 可配置的 PW…

Go:方法

方法聲明 type point struct { X, Y float64 }// 普通函數 func Distance(p, q Point) float64 {return math.Hypot(q.x - p.x, q.y - p.Y) }// Point類型的方法 func (p Point) Distance(q Point) float64 {return math.Hypot(q.x - p.x, q.y - p.Y) }方法聲明與普通函數聲…

前端基礎之《Vue(4)—響應式原理》

一、什么是響應式 1、響應式英文reactive 當你get/set一個變量時&#xff0c;你有辦法可以“捕獲到”這種行為。 2、一個普通對象和一個響應式對象對比 &#xff08;1&#xff09;普通對象 <script>// 這種普通對象不具備響應式var obj1 {a: 1,b: 2} </script>…

【技術派部署篇】Windows本地部署技術派

一、技術派簡介 技術派是一個采用 Spring Boot、MyBatis-Plus、MySQL、Redis、ElasticSearch、MongoDB、Docker、RabbitMQ 等技術棧的社區系統&#xff0c;其 1.0 版已正式上線。該項目的技術棧按階段集成引入&#xff0c;開發者可根據自身需求選擇不同版本進行學習。 二、環…

DeepSeek和ChatGPT的全面對比

DeepSeek和ChatGPT作為當前領先的大語言模型&#xff0c;代表了AI發展的不同技術路徑和應用理念。以下從技術架構到用戶體驗的全面對比分析&#xff0c;將揭示兩者在AI競賽中的獨特定位。 一、模型架構與原理 1. DeepSeek 架構特點&#xff1a;采用混合專家系統&#xff08;…