go 原子操作

2021-10-06 06:25:23 字數 2255 閱讀 6888

atmoic包可以對int32、int64、uint32、uint64、uintptr、unsafe.pointer提供五種原子性操作分別是增或減、比較並交換、載入、儲存和交換。

atomic包中有類似addint32等這樣的方法,它需要兩個引數,第乙個是需要修改的int32型別的變數位址,第二個是add到該變數上且與改變量型別相同的值。

我們的例子是用10個執行緒每個執行緒都將變數value(初始值為0)增加1000次,那麼最終結果是10000。不用原子操作的話我們可以用channel或mutex來實現來保證對value++的操作的原子性。atomic包提供的addint32等此類的方法同樣可以實現value++操作的原子性並且效率更高。

func

main()

waitgroup.

add(10)

for i:=

0;i<

10;i++

waitgroup.

done()

}()}

waitgroup.

wait()

fmt.

println

(count)

}

輸出的結果是10000與預期相符合。

以compareandswapint32為例,函式宣告為

func

compareandswapint32

(addr *

int32

,old,

newint32

))

該方法會比較需要修改的目標變數位址(addr)中的值與讀取出來的目標變數的值(old)是否一致,一致的話將目標變數位址指向的值更新為new否則更新操作就會被忽略。

cas與鎖相比,鎖的做法是悲觀的因為鎖總是認為在操作目標變數時總是有其他執行緒對該目標變數進行修改。而cas更趨於樂觀,它總是假定沒有其他執行緒對當前目標變數進行修改。

該方法適用於被操作的值不會被其他執行緒頻繁更新的情景,如果被操作的值被其他執行緒頻繁更新則不建議使用cas。

我們使用compareandswap方法代替上面的addint方法,其中for迴圈是迴圈等待直到更新成功才會推出for迴圈。

func

main()

waitgroup.

add(10)

for i:=

0;i<

10;i++

} waitgroup.

done()

}()}

waitgroup.

wait()

fmt.

println

(count)

}

執行結果是10000符合預期結果。

原子性的載入可以保證你在讀取目標變數時沒有其他執行緒對該變數進行讀寫。

其使用方法為

var value=

int32(1

)result:=atomic.

loadint32

(&value)

在原子的儲存某個值過程中,任何cpu都不會進行針對該值的讀寫操作。原子儲存並不關心被操作的舊值是什麼,它只是單純的將舊值替換成新值。

以int32為例原子儲存的方法宣告如下

func

storeint32

(addr *

int32

,new

int32

)

在原子的交換某個值過程中,任何cpu都不會進行針對該值的讀寫操作。原子交接並不會關心被操作的舊值,它比原子儲存操作多乙個步驟就是返回舊值。

函式宣告如下:

func swapint32(addr *int32, new int32) (old int32)

atomic.value是乙個結構體型別稱為"原子值型別",它用於儲存需要原子讀寫的值。其接受的被操作的值型別不限。

宣告乙個原子值如下:

var atomicval atomic.value
該型別有兩個公開的指標方法load和stroe。load可以原子地讀取原子值中儲存的值,返回乙個inte***ce型別的引數而沒有任何結果。在未曾通過store方法向原子值例項儲存值之前,它的load方法總會返回nil。

原子值例項的store方法傳入的引數不能為nil,並且每次傳入的引數的型別必須一致。

注意如果atomic.value型別的值在傳入其他函式時,一定要傳 *atmoic.value型別,否則傳入的是atmoic的拷貝就會失去原子性。

go 原子操作 atomic的使用

go語言提供的原子操作都是非侵入式的,它們由標準庫 包sync atomic中的眾多函式代表。我們呼叫sync atomic中的幾個函式可以對幾種簡單的型別進行原子操作。這些型別包括int32,int64,uint32,uint64,uintptr,unsafe.pointer,共6個。這些函式的原...

原子性,原子操作

舉個例子 a想要從自己的帳戶中轉1000塊錢到b的帳戶裡。那個從a開始轉帳,到轉帳結束的這乙個過程,稱之為乙個事務。在這個事務裡,要做如下操作 從a的帳戶中減去1000塊錢。如果a的帳戶原來有3000塊錢,現在就變成2000塊錢了。在b的帳戶裡加1000塊錢。如果b的帳戶如果原來有2000塊錢,現在...

mysql 原子鎖 Go語言檔案鎖操作

我們使用go語言開發一些程式的時候,往往出現多個程序同時操作同一份檔案的情況,這很容易導致檔案中的資料混亂。這時我們就需要採用一些手段來平衡這些衝突,檔案鎖 flock 應運而生,下面我們就來介紹一下。對於 flock,最常見的例子就是 nginx,程序執行起來後就會把當前的 pid 寫入這個檔案,...