cas[cpu 硬體同步原語(compare and swap)]

支持並發的第一個處理器提供原子的測試並設定操作,通常在單位上運行這項操作。現在的處理器(包括 Intel 和 Sparc 處理器)使用的最通用的方法是實現名為 比較並轉換或 CAS 的原語。(在 Intel 處理器中,比較並交換通過指令的 cmpxchg 系列實現。PowerPC 處理器有一對名為“載入並保留”和“條件存儲”的指令,它們實現相同的目地;MIPS 與 PowerPC 處理器相似,除了第一個指令稱為“載入連結”。)

CAS 操作包含三個運算元 —— 記憶體位置(V)、預期原值(A)和新值(B)。如果記憶體位置的值與預期原值相匹配,那么處理器會自動將該位置值更新為新值。否則,處理器不做任何操作。無論哪種情況,它都會在 CAS 指令之前返回該位置的值。(在 CAS 的一些特殊情況下將僅返回 CAS 是否成功,而不提取當前值。)CAS 有效地說明了“我認為位置 V 應該包含值 A;如果包含該值,則將 B 放到這個位置;否則,不要更改該位置,只告訴我這個位置現在的值即可。”

通常將 CAS 用於同步的方式是從地址 V 讀取值 A,執行多步計算來獲得新值 B,然後使用 CAS 將 V 的值從 A 改為 B。如果 V 處的值尚未同時更改,則 CAS 操作成功。

類似於 CAS 的指令允許算法執行讀-修改-寫操作,而無需害怕其他執行緒同時修改變數,因為如果其他執行緒修改變數,那么 CAS 會檢測它(並失敗),算法可以對該操作重新計算。清單 3 說明了 CAS 操作的行為(而不是性能特徵),但是 CAS 的價值是它可以在硬體中實現,並且是極輕量級的(在大多數處理器中)。

Java中的CAS操作

在JDK 1.5之後,Java 程式才可以使用CAS操作,該操作由sun.misc.Unsafe類裡面的compareAndSwapInt()和compareAndSwapLong()等幾個方法包裝提供,虛擬機在內部對這些方法做了特殊處理,即時編譯出來的結果就是一條平台相關的處理器CAS指令,沒有方法調用的過程,或者可以認為是無條件內聯進去了。

由於Unsafe類不是提供給用戶提供調用的類(Unsafe.getUnsafe()的代碼中限制了只有啟動類載入器(Bootstrap ClassLoader)載入的Class才能訪問它),因此,如果不採用反射手段,我們只能通過其他的Java API來間接使用它,如J.U.C包裡面的整數原子類,其中的 compareAndSet()和 getAndIncrement()等方法都使用了 Unsafe 類的 CAS 操作。

相關詞條

熱門詞條

聯絡我們