日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CAS操作原理与实现

發布時間:2024/3/24 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CAS操作原理与实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 一、樂觀鎖和悲觀鎖
    • 1.1樂觀鎖
    • 1.2悲觀鎖
    • 1.3自旋鎖
  • 二、CAS
    • 2.1什么是CAS?
    • 2.2ABA 問題
  • 總結


前言

Java中的鎖主要用于保障線程在多并發情況下數據的一致性。鎖從樂觀和悲觀的角度可分為樂觀鎖和悲觀鎖,JVM還巧妙的設計了自旋鎖更快的使用CPU資源。


一、樂觀鎖和悲觀鎖

1.1樂觀鎖

樂觀鎖采用樂觀的思想處理數據,即每次讀取數據時都認為別人不會修改該數據,不會進行加鎖。

JAVA中的樂觀鎖大部分是通過CAS操作實現的,CAS是一種原子更新操作,對數據操作之前會比較要更新的值和預期的值是否相同,如果相同才會進行更新,否則會再次嘗試,直到成功。

1.2悲觀鎖

悲觀鎖采用悲觀的思想處理數據,認為每次讀取數據時別人都會修改數據,所以每次讀寫數據都會加鎖,不允許別的線程同時操作。

JAVA中的悲觀鎖大部分基于AQS(抽象的隊列同步器)實現。AQS定義了一套多線程訪問共享資源的同步框架,許多同步類的實現都依賴它,例如:ReentranLock等。

1.3自旋鎖

自旋鎖( SpinLock),spin在英文中用于描述紡紗的紗輪瘋狂自轉的樣子。認為如果持有鎖的線程在很短的時間就會釋放鎖資源,那么等待的線程只需要等一等,重試不斷的去嘗試獲取鎖(自旋),不需要進入阻塞、掛起狀態。

自旋鎖的優點
1.非常適合占用鎖時間非常短的場景,極大提高鎖的效率,自旋等待的時間明顯少于線程阻塞掛起和在喚醒所用的時間。

自旋鎖缺點:
如果線程占用鎖時間過長,線程在自旋的時候會長時間獲取不到鎖,造成CPU資源浪費。


二、CAS

2.1什么是CAS?

CAS 是樂觀鎖的一種實現方式,他采用的是自旋鎖(一直嘗試,直到成功)的思想,是一種輕量級的鎖機制。

CAS(Compare And Swap)指比較并交換。CAS算法CAS(V,E,N)包含三個參數,V表示要更新的變量,E表示預期的值,N表示新值。僅在V值等于E值,才會將V值設為N,如果V值和E值不同,表示有其他線程進行更新,當前線程什么都不做,不會被掛起,允許再次嘗試,直到成功

從JDK 1.5開始提供了java.util.concurrent.atomic包,在該包中提供了許多基于CAS實現的原子操作類,用法方便,性能高效。我們以AtomicInteger為例進行分析CAS的JAVA實現代碼。

JDK1.7

public class AtomicInteger extends Number implements java.io.Serializable {private volatile int value;public final int get() {return value;}//JDK 1.7的源碼,由for的死循環實現,并且直接在AtomicInteger實現該方法,//JDK1.8后,直接調用getAndAddInt方法即可public final int getAndIncrement() {for(;;){ //CAS自旋,一直嘗試,直到成功int current=get();int next=current+1;if(compareAndSet(current,next)){return current;} }}public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}}

JDK1.8

//AtomicInteger中的方法public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}//Unsafe中的方法public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {var5 = this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));return var5;}

CAS是采用了樂觀鎖的思想,總是認為自己可以成功完成操作。有多個線程同時使用CAS操作同一個變量時只有一個會成功更新,其余均會失敗。

2.2ABA 問題

第一個線程從內存的V位置取出了A,第二個線程也從內存的V位置取出了A,先修改成B,然后又修改成了A,第一個線程在進行CAS操作時不會察覺到異常,雖然操作正常進行,但該數據已經發生過變化,某些應用場景下可能出現數據不一致的問題。

解決辦法:添加版本號,執行操作時加上一個版本號,版本號一致性可以進行操作,否則失敗。每次操作版本號增加,因為版本號只會增加不會減少,所以不會出現ABA問題。

例如:
1.線程1讀取A(1)
2.線程2讀取A(1),修改成B(2),又修改成A(3),
3.線程1讀取預期值,發現預期值A(3)和變量值A(1)不同,不進行操作。


總結

除了本文提到的鎖的類型,鎖從獲取資源的公平性角度可以分為公平鎖和非公平鎖,從是否共享資源的角度可分為共享鎖和獨占鎖,從鎖的狀態可分為偏向鎖、輕量級鎖和重量級鎖,后續會介紹這些鎖的特性。本文的重點CAS,理解了CAS就理解了樂觀鎖和自旋鎖的特點,對于比較并交換的過程一定要牢記于心。


總結

以上是生活随笔為你收集整理的CAS操作原理与实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。