Java中的CAS(Compare-And-Swap)操作示例詳解
Java面試題 - 什么是Java 的 CAS(Compare-And-Swap)操作?
什么是CAS操作?
CAS(Compare-And-Swap,比較并交換)是一種原子操作,用于在多線程環(huán)境中實現(xiàn)無鎖(lock-free)的線程安全編程。它是現(xiàn)代并發(fā)編程中的基礎操作之一,Java中的許多并發(fā)工具類(如AtomicInteger、AtomicReference等)都是基于CAS實現(xiàn)的。
CAS操作包含三個操作數(shù):
- 內存位置(V)
- 預期原值(A)
- 新值(B)
當且僅當內存位置V的值等于預期原值A時,處理器才會將該位置的值更新為新值B,否則不執(zhí)行任何操作。無論哪種情況,都會返回該位置原來的值。
CAS操作的基本流程

Java中的CAS實現(xiàn)
在Java中,CAS操作主要通過sun.misc.Unsafe類提供的一系列方法實現(xiàn),這些方法最終會調用本地(native)方法,由JVM借助CPU的CAS指令完成。
Java并發(fā)包(java.util.concurrent.atomic)中的原子類(如AtomicInteger)提供了對CAS操作的封裝:
public class AtomicInteger extends Number implements java.io.Serializable {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private volatile int value;
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
// 其他方法...
}CAS操作示例
下面是一個使用AtomicInteger的簡單示例:
import java.util.concurrent.atomic.AtomicInteger;
public class CASExample {
private static AtomicInteger counter = new AtomicInteger(0);
public static void main(String[] args) {
// 初始值為0
System.out.println("初始值: " + counter.get());
// 嘗試將0更新為1(會成功)
boolean success1 = counter.compareAndSet(0, 1);
System.out.println("CAS(0,1)結果: " + success1 + ", 當前值: " + counter.get());
// 嘗試將0更新為2(會失敗,因為當前值已經是1)
boolean success2 = counter.compareAndSet(0, 2);
System.out.println("CAS(0,2)結果: " + success2 + ", 當前值: " + counter.get());
}
}輸出結果:
初始值: 0
CAS(0,1)結果: true, 當前值: 1
CAS(0,2)結果: false, 當前值: 1
CAS的典型應用場景
- 原子類:如AtomicInteger、AtomicLong、AtomicReference等
- 并發(fā)容器:如ConcurrentHashMap的部分實現(xiàn)
- 鎖機制:如AQS(AbstractQueuedSynchronizer)的實現(xiàn)基礎
- 計數(shù)器:無鎖的線程安全計數(shù)器
CAS的優(yōu)缺點
優(yōu)點
- 高性能:避免了線程阻塞和上下文切換的開銷
- 無鎖:減少了死鎖的可能性
- 可擴展性:在高并發(fā)環(huán)境下表現(xiàn)良好
缺點
- ABA問題:如果一個值從A變成B,然后又變回A,CAS會認為它沒有變化過
- 解決方案:使用版本號或時間戳(如AtomicStampedReference)

- 循環(huán)時間長開銷大:如果CAS失敗,通常會循環(huán)重試,長時間不成功會消耗CPU資源
- 只能保證一個共享變量的原子操作:對于多個共享變量,需要使用AtomicReference來封裝
CAS與鎖的比較
| 特性 | CAS | 鎖 |
|---|---|---|
| 線程阻塞 | 不會阻塞(樂觀鎖) | 會阻塞(悲觀鎖) |
| 實現(xiàn)復雜度 | 較高 | 相對簡單 |
| 適用場景 | 低沖突、簡單操作 | 高沖突、復雜操作 |
| 性能 | 無上下文切換,開銷小 | 有上下文切換,開銷大 |
| 公平性 | 不保證公平性 | 可保證公平性 |
總結
CAS是Java并發(fā)編程中的重要概念,它提供了一種高效的無鎖線程安全機制。理解CAS的工作原理對于編寫高性能并發(fā)程序至關重要。雖然CAS有ABA問題等局限性,但通過適當?shù)慕鉀Q方案(如版本號)可以規(guī)避這些問題。在適當?shù)膱鼍跋率褂肅AS,可以顯著提高程序的并發(fā)性能。
到此這篇關于Java中的CAS(Compare-And-Swap)操作示例詳解的文章就介紹到這了,更多相關Java CAS操作內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBean管理與Spring Boot自動配置原理解析
在Spring中,Bean的作用域(Scope)決定了Bean的實例化方式以及其生命周期,下面給大家介紹SpringBean管理與Spring Boot自動配置原理解析,感興趣的朋友一起看看吧2025-05-05
spring boot結合Redis實現(xiàn)工具類的方法示例
這篇文章主要介紹了spring boot結合Redis實現(xiàn)工具類的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11
詳解Java的內置異常以及創(chuàng)建自定義異常子類的方法
這篇文章主要介紹了詳解Java的內置異常以及創(chuàng)建自定義異常子類的方法,是Java入門學習中的基礎知識,需要的朋友可以參考下2015-09-09
MyBatis中insert操作返回主鍵的實現(xiàn)方法
在使用MyBatis做持久層時,insert語句默認是不返回記錄的主鍵值,而是返回插入的記錄條數(shù)。這篇文章主要介紹了MyBatis中insert操作返回主鍵的方法,需要的朋友可以參考下2016-09-09
Java-Io-RandomAccessFile任意位置讀寫數(shù)據(jù)的操作小結
RandomAccessFile類支持隨機訪問方式,可以跳轉到文件的任意位置讀寫數(shù)據(jù),這個類在文件隨機讀取時有很大的優(yōu)勢,可利用多線程完成對一個大文件的讀寫,本文給大家介紹Java-Io-RandomAccessFile(任意位置讀寫數(shù)據(jù))的相關知識,需要的朋友可以參考下2022-05-05
Java利用JSONPath操作JSON數(shù)據(jù)的技術指南
JSONPath?是一種強大的工具,用于查詢和操作?JSON?數(shù)據(jù),類似于?SQL?的語法,它為處理復雜的?JSON?數(shù)據(jù)結構提供了簡單且高效的解決方案,本文將介紹?JSONPath?的基本語法,并通過詳細的?Java?示例展示其實際應用,需要的朋友可以參考下2025-04-04

