cas原理
在計(jì)算機(jī)科學(xué)中,比較和交換(compare and swap)是用于實(shí)現(xiàn)多線程同步的原子指令。 它將內(nèi)存位置的內(nèi)容與給定值進(jìn)行比較,只有在相同的情況下,將該內(nèi)存位置的內(nèi)容修改為新的給定值。 這是作為單個(gè)原子操作完成的。 原子性保證新值基于最新信息計(jì)算; 如果該值在同一時(shí)間被另一個(gè)線程更新,則寫(xiě)入將失敗。 操作結(jié)果必須說(shuō)明是否進(jìn)行替換; 這可以通過(guò)一個(gè)簡(jiǎn)單的布爾響應(yīng)(這個(gè)變體通常稱(chēng)為比較和設(shè)置),或通過(guò)返回從內(nèi)存位置讀取的值來(lái)完成(摘自維基本科)
cas流程
以atomicinteger.addandget()為例講解cas
javadoc
public final int addandget?(int delta)
atomically adds the given value to the current value, with memory effects as specified by varhandle.getandadd(java.lang.object…).
parameters:
delta - the value to add
returns:
the updated value
在java的源碼中
1
2
3
|
public final int addandget( int delta) { return u.getandaddint( this , value, delta) + delta; } |
這里的value是在該類(lèi)初始化的時(shí)候獲取到的,理解一下就是這時(shí)候我們調(diào)用unsafe的objectfieldoffset
從atomic類(lèi)文件中獲取value的偏移量,那么value
其實(shí)就是記錄value的偏移量的。
value準(zhǔn)確的是value這個(gè)字段相對(duì)與atomicinteger這個(gè)對(duì)象內(nèi)存起始地址的偏移量,由于這個(gè)方法的最底層是jni調(diào)用native的方法,所以需要傳入這個(gè)值。
1
|
private static final long value = u.objectfieldoffset(atomicinteger. class , "value" ); |
繼續(xù)往下執(zhí)行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/** * atomically adds the given value to the current value of a field * or array element within the given object {@code o} * at the given {@code offset}. * @param o object/array to update the field/element in * @param offset field/element offset * @param delta the value to add * @return the previous value * @since 1.8 **/ @hotspotintrinsiccandidate public final int getandaddint(object o, long offset, int delta) { int v; do { v = getintvolatile(o, offset); } while (!weakcompareandsetint(o, offset, v, v + delta)); return v; } |
1
2
3
4
5
6
|
@hotspotintrinsiccandidate public final boolean weakcompareandsetint(object o, long offset, int expected, int x) { return compareandsetint(o, offset, expected, x); } |
如果obj內(nèi)的value和expect相等,就證明沒(méi)有其他線程改變過(guò)這個(gè)變量,那么就更新它為update,如果這一步的cas沒(méi)有成功,那就采用自旋的方式繼續(xù)進(jìn)行cas操作。從代碼中看著也是兩個(gè)步驟,但其實(shí)在jni里是借助于一個(gè)cpu指令完成的,實(shí)際還是原子操作。
aba問(wèn)題
產(chǎn)生aba問(wèn)題的原因
cas需要在操作值的時(shí)候檢查下值有沒(méi)有發(fā)生變化,如果沒(méi)有發(fā)生變化則更新,但是如果一個(gè)值原來(lái)是a,變成了b,又變成了a,那么使用cas進(jìn)行檢查時(shí)會(huì)發(fā)現(xiàn)它的值沒(méi)有發(fā)生變化,但是實(shí)際上卻變化了。這就是cas的aba問(wèn)題。
如何規(guī)避aba問(wèn)題
常用的辦法是在更新數(shù)據(jù)的時(shí)候加入版本號(hào),以版本號(hào)來(lái)控制更新。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)服務(wù)器之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
原文鏈接:https://blog.csdn.net/u012449363/article/details/86549823