【多線程】CAS原理

引言

  在Java併發包中有這樣一個包,java.util.concurrent.atomic,該包是對Java部分數據類型的原子封裝,在原有數據類型的基礎上,提供了原子性的操作方法,保證了線程安全。那他們是如何保證線程安全的那,採用了CAS機制:

CAS

  CAS 指的是現代 CPU 廣泛支持的一種對內存中的共享數據進行操作的一種特殊指令(底層用C實現的)。這個指令會對內存中的共享數據做原子的讀寫操作。CAS比較與交換的僞代碼可以表示爲:

do{   
       備份舊數據;  
       基於舊數據構造新數據;  
}while(!CAS( 內存地址,備份的舊數據,新數據 ))  

  指令的操作過程:首先,CPU 會將內存中將要被更改的數據與期望的值做比較。然後,當這兩個值相等時,CPU 纔會將內存中的數值替換爲新的值。否則便不做操作。最後,CPU 會將舊的數值返回。這一系列的操作是原子的。它們雖然看似複雜,但卻是 Java 5 併發機制優於原有鎖機制的根本。簡單來說,CAS 的含義是“我認爲原有的值應該是什麼,如果是,則將原有的值更新爲新值,否則不做修改,並告訴我原來的值是多少”。
  簡單的來說,CAS有3個操作數,內存值V,舊的預期值A,要修改的新值B,“我認爲V的值應該爲A,如果是,那麼將V的值更新爲B,否則不修改並告訴V的值實際爲多少”,CAS是樂觀鎖技術,當多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程並不會被掛起,而是被告知這次競爭中失敗,並可以再次嘗試

CAS缺點

問題基本是這個樣子:

  1. 進程P1在共享變量中讀到值爲A
  2. P1被搶佔了,進程P2執行
  3. P2把共享變量裏的值從A改成了B,再改回到A,此時被P1搶佔。
  4. P1回來看到共享變量裏的值沒有被改變,於是繼續執行。

雖然P1以爲變量值沒有改變,繼續執行了,但是這個會引發一些潛在的問題。ABA問題最容易發生在lock free 的算法中的,CAS首當其衝,因爲CAS判斷的是指針的地址。如果這個地址被重用了呢,問題就很大了。(地址被重用是很經常發生的,一個內存分配後釋放了,再分配,很有可能還是原來的地址)。就如:你拿着一個裝滿錢的手提箱在飛機場,此時過來了一個火辣性感的美女,然後她很暖昧地挑逗着你,並趁你不注意的時候,把用一個一模一樣的手提箱和你那裝滿錢的箱子調了個包,然後就離開了,你看到你的手提箱還在那,於是就提着手提箱去趕飛機去了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章