java中樂觀鎖CAS操作詳解

2021-09-01 11:55:19 字數 863 閱讀 1969

樂觀鎖就是假設所有執行緒訪問共享資源都不會出現衝突,由於不會出現衝突所以就不會也不需要去阻塞其他執行緒。因此執行緒不會出現阻塞等待的狀態。但是一旦發生衝突時,無鎖操作,會使用cas操作來鑑別執行緒是否出現衝突,出現衝突了就重複嘗試,直到沒有衝突為止。

cas操作就是compare and swap比較交換操作。

在cas中操作中,有三個值。v,o,n。

v:當前記憶體中存放的值

o:當前執行緒期望記憶體中現在存放的值

n:當前執行緒希望將記憶體中的值更新的新值。

1.比較操作 -比較v和o

當v == o時,表示當初記憶體中存放的值,就是我預期的值。也就是說,該值放進入沒有被其他任何執行緒修改過。o值就是目前記憶體中存的值。因此,此時可以將n值賦給v,更新記憶體裡的值。

當v != o時,表示當前的值已經被其他執行緒修改過了,因為o值不是記憶體中實際的值,所以無法修改,並且將v值返回,將o值修改為v值,以便於下次嘗試。

當有多個執行緒使用cas操作時,只有乙個執行緒可以替換成功,其餘的執行緒均會失敗,失敗的執行緒會不斷重新嘗試(自旋)或者進入阻塞狀態。

1.浪費cpu資源

首先cas採用自旋方法,而不使得沒有獲取鎖的執行緒阻塞,自旋一直處於cpu執行狀態,但是進行的是無用功,所以這種行為會大大浪費處理器資源。

2.存在公平性問題

由於cas操作使得執行緒不斷自旋式嘗試獲取鎖,速度自然比喚醒等待執行緒快的多。所以存在公平性問題,無法實現公平機制。

3.存在aba問題

舉個例子:假設當前執行緒為a,b執行緒知道現在是a執行緒,所以將a->b。此時當前執行緒為b。此時a再來將b->a。又換回a。這時c來了,c看見a希望將a替換成c。但是此時的a非一開始的a了。本來是不應該c->a的,但是因為不知道先前a和現在a的區別。所以進行了替換。

樂觀鎖與CAS操作

atomicinteger來研究在沒有鎖的情況下是如何做到資料正確性的?這裡舉例說明乙個方法 getandincrement public final int getandincrement 這裡面有個compareandset方法,其實是jni呼叫,在這裡採用了cas操作,每次從記憶體中讀取資料然...

java中樂觀鎖和悲觀鎖的區別

悲觀鎖 pessimistic lock 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。它指的是對資料被外...

CAS 樂觀鎖策略

cas,即compare and swap,比較後再交換,使用的場景 執行緒1執行如下指令 read a a write a 執行緒2執行如下指令 read a a write a 此時有這樣的執行順序 此時如果a的初始值為0,那麼兩個執行緒執行完最後的結果為1,而不是2。如下 public fin...