最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang?Compare?And?Swap算法詳細(xì)介紹

 更新時(shí)間:2022年10月11日 09:46:28   作者:~龐貝  
CAS算法是一種有名的無(wú)鎖算法。無(wú)鎖編程,即不使用鎖的情況下實(shí)現(xiàn)多線程之間的變量同步,也就是在沒(méi)有線程被阻塞的情況下實(shí)現(xiàn)變量的同步,所以也叫非阻塞同步Non-blocking?Synchronization

CAS算法(compare and swap)

CAS算法涉及到三個(gè)操作數(shù)

  • 需要讀寫(xiě)的內(nèi)存值V
  • 進(jìn)行比較的值A(chǔ)
  • 擬寫(xiě)入的新值B

當(dāng)且僅當(dāng) V 的值等于 A時(shí),CAS通過(guò)原子方式用新值B來(lái)更新V的值,否則不會(huì)執(zhí)行任何操作(比較和替換是一個(gè)原子操作)。一般情況下是一個(gè)自旋操作,即不斷的重試。

CAS算法(Compare And Swap),是原子操作的一種, CAS算法是一種有名的無(wú)鎖算法。無(wú)鎖編程,即不使用鎖的情況下實(shí)現(xiàn)多線程之間的變量同步,也就是在沒(méi)有線程被阻塞的情況下實(shí)現(xiàn)變量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)??捎糜谠诙嗑€程編程中實(shí)現(xiàn)不被打斷的數(shù)據(jù)交換操作,從而避免多線程同時(shí)改寫(xiě)某一數(shù)據(jù)時(shí)由于執(zhí)行順序不確定性以及中斷的不可預(yù)知性產(chǎn)生的數(shù)據(jù)不一致問(wèn)題。

該操作通過(guò)將內(nèi)存中的值與指定數(shù)據(jù)進(jìn)行比較,當(dāng)數(shù)值一樣時(shí)將內(nèi)存中的數(shù)據(jù)替換為新的值。

Go中的CAS操作是借用了CPU提供的原子性指令來(lái)實(shí)現(xiàn)。CAS操作修改共享變量時(shí)候不需要對(duì)共享變量加鎖,而是通過(guò)類(lèi)似樂(lè)觀鎖的方式進(jìn)行檢查,本質(zhì)還是不斷的占用CPU 資源換取加鎖帶來(lái)的開(kāi)銷(xiāo)(比如上下文切換開(kāi)銷(xiāo))。

package main
import (
	"fmt"
	"sync"
	"sync/atomic"
)
var (
	counter int32          //計(jì)數(shù)器
	wg      sync.WaitGroup //信號(hào)量
)
func main() {
	threadNum := 5
	wg.Add(threadNum)
	for i := 0; i < threadNum; i++ {
		go incCounter(i)
	}
	wg.Wait()
}
func incCounter(index int) {
	defer wg.Done()
	spinNum := 0
	for {
		// 原子操作
		old := counter
		ok := atomic.CompareAndSwapInt32(&counter, old, old+1)
		if ok {
			break
		} else {
			spinNum++
		}
	}
	fmt.Printf("thread,%d,spinnum,%d\n", index, spinNum)
}

當(dāng)主函數(shù)main首先創(chuàng)建了5個(gè)信號(hào)量,然后開(kāi)啟五個(gè)線程執(zhí)行incCounter方法,incCounter內(nèi)部執(zhí)行, 使用cas操作遞增counter的值,atomic.CompareAndSwapInt32具有三個(gè)參數(shù),第一個(gè)是變量的地址,第二個(gè)是變量當(dāng)前值,第三個(gè)是要修改變量為多少,該函數(shù)如果發(fā)現(xiàn)傳遞的old值等于當(dāng)前變量的值,則使用第三個(gè)變量替換變量的值并返回true,否則返回false。

這里之所以使用無(wú)限循環(huán)是因?yàn)樵诟卟l(fā)下每個(gè)線程執(zhí)行CAS并不是每次都成功,失敗了的線程需要重寫(xiě)獲取變量當(dāng)前的值,然后重新執(zhí)行CAS操作。讀者可以把線程數(shù)改為10000或者更多就會(huì)發(fā)現(xiàn)輸出thread,5329,spinnum,1其中這個(gè)1就說(shuō)明該線程嘗試了兩個(gè)CAS操作,第二次才成功。

因此呢, go中CAS操作可以有效的減少使用鎖所帶來(lái)的開(kāi)銷(xiāo),但是需要注意在高并發(fā)下這是使用cpu資源做交換的。

CAS是如何運(yùn)行的

我們有兩個(gè)goroutineA和goroutineB,接下來(lái)我們簡(jiǎn)稱 A 和 B, 共享資源稱為C

  • A 和 B 均保存 C 當(dāng)前的值
  • A 嘗試使用CAS(56,53)更新C的值
  • C目前為56,可以更新,然后更新成功
  • B嘗試使用CAS(56,53)更新C的值
  • C已經(jīng)為53,更新失敗

Go中的CAS源碼

// CompareAndSwapUint32 executes the compare-and-swap operation for a uint32 value.
func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)

實(shí)際代碼文件在

Go / src / runtime / internal / atomic / asm_amd.s文件中

TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-25
 MOVQ ptr+0(FP), BX
 MOVQ old+8(FP), AX
 MOVQ new+16(FP), CX
 LOCK
 CMPXCHGQ CX, 0(BX)
 SETEQ ret+24(FP)
 RET

其中我們可以看作

lock(一個(gè)命令前綴,在這里用于CMPXCHGQ)可以鎖住總線保證多次內(nèi)存操作的原子性。

然后執(zhí)行CMPXCHGQ

cmpxchg %cx, %bx;如果AX與BX相等,則CX送BX且ZF置1;否則BX送CX,且ZF清0

  • 拿AX(old) 與 BX(共享數(shù)據(jù)ptr) 做對(duì)比。
  • 相等,則修改BX(共享數(shù)據(jù)ptr),狀態(tài)碼ZX設(shè)置為 1 。
  • 不相等,則將CX(new)置為目前BX(共享數(shù)據(jù)ptr)的值, 狀態(tài)碼ZX設(shè)置為 0

CAS的缺陷

CAS在共享資源競(jìng)爭(zhēng)比較激烈的時(shí)候,每個(gè)goroutine會(huì)容易處于自旋狀態(tài),影響效率,在競(jìng)爭(zhēng)激烈的時(shí)候推薦使用鎖。

無(wú)法解決ABA問(wèn)題

ABA問(wèn)題是無(wú)鎖結(jié)構(gòu)實(shí)現(xiàn)中常見(jiàn)的一種問(wèn)題,可基本表述為:

進(jìn)程P1讀取了一個(gè)數(shù)值A(chǔ)

P1被掛起(時(shí)間片耗盡、中斷等),進(jìn)程P2開(kāi)始執(zhí)行

P2修改數(shù)值A(chǔ)為數(shù)值B,然后又修改回A

P1被喚醒,比較后發(fā)現(xiàn)數(shù)值A(chǔ)沒(méi)有變化,程序繼續(xù)執(zhí)行。

到此這篇關(guān)于Golang Compare And Swap算法詳細(xì)介紹的文章就介紹到這了,更多相關(guān)Golang CAS算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go框架三件套Gorm?Kitex?Hertz基本用法與常見(jiàn)API講解

    Go框架三件套Gorm?Kitex?Hertz基本用法與常見(jiàn)API講解

    這篇文章主要為大家介紹了Go框架三件套Gorm?Kitex?Hertz的基本用法與常見(jiàn)API講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>
    2023-02-02
  • Golang channle管道的基本使用及快速入門(mén)

    Golang channle管道的基本使用及快速入門(mén)

    管道是Go語(yǔ)言中實(shí)現(xiàn)并發(fā)的一種方式,它可以在多個(gè)goroutine之間進(jìn)行通信和數(shù)據(jù)交換,本文主要介紹了Golang channle管道的基本使用及快速入門(mén),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • go?sync包中的互斥鎖Mutex和等待組WaitGroup使用詳解

    go?sync包中的互斥鎖Mutex和等待組WaitGroup使用詳解

    這篇文章主要為大家介紹了go?sync包中的互斥鎖Mutex和等待組WaitGroup使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • goland設(shè)置顏色和字體的操作

    goland設(shè)置顏色和字體的操作

    這篇文章主要介紹了goland設(shè)置顏色和字體的操作方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05
  • 解密Golang中Request對(duì)象的操作

    解密Golang中Request對(duì)象的操作

    這篇文章主要和大家深入探討?Golang?中的?Request?對(duì)象,并從多個(gè)方面介紹其功能、結(jié)構(gòu)和使用方法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2023-05-05
  • GoLang context包的使用方法介紹

    GoLang context包的使用方法介紹

    日常Go開(kāi)發(fā)中,Context包是用的最多的一個(gè)了,幾乎所有函數(shù)的第一個(gè)參數(shù)都是ctx,那么我們?yōu)槭裁匆獋鬟fContext呢,Context又有哪些用法,底層實(shí)現(xiàn)是如何呢?相信你也一定會(huì)有探索的欲望,那么就跟著本篇文章,一起來(lái)學(xué)習(xí)吧
    2023-03-03
  • 詳解Golang 推薦的命名規(guī)范

    詳解Golang 推薦的命名規(guī)范

    這篇文章主要介紹了詳解Golang 推薦的命名規(guī)范,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • Go語(yǔ)言集成mysql驅(qū)動(dòng)、調(diào)用數(shù)據(jù)庫(kù)、查詢數(shù)據(jù)操作示例

    Go語(yǔ)言集成mysql驅(qū)動(dòng)、調(diào)用數(shù)據(jù)庫(kù)、查詢數(shù)據(jù)操作示例

    這篇文章主要介紹了Go語(yǔ)言集成mysql驅(qū)動(dòng)、調(diào)用數(shù)據(jù)庫(kù)、查詢數(shù)據(jù)操作,結(jié)合實(shí)例形式分析了Go語(yǔ)言安裝mysql驅(qū)動(dòng)包、連接mysql數(shù)據(jù)庫(kù)及查詢等相關(guān)操作技巧,需要的朋友可以參考下
    2019-06-06
  • Go使用sync.Pool提高性能的代碼示例

    Go使用sync.Pool提高性能的代碼示例

    在高性能應(yīng)用程序中,頻繁的內(nèi)存分配和回收是性能瓶頸的常見(jiàn)原因之一,Go 語(yǔ)言提供了 sync.Pool 類(lèi)型,它可以用來(lái)存儲(chǔ)和重用臨時(shí)對(duì)象,本文將詳細(xì)介紹如何在 Go 中使用 sync.Pool,并通過(guò)實(shí)際代碼示例來(lái)展示其對(duì)性能的提升效果,需要的朋友可以參考下
    2024-04-04
  • Golang中數(shù)據(jù)結(jié)構(gòu)Queue的實(shí)現(xiàn)方法詳解

    Golang中數(shù)據(jù)結(jié)構(gòu)Queue的實(shí)現(xiàn)方法詳解

    這篇文章主要給大家介紹了關(guān)于Golang中數(shù)據(jù)結(jié)構(gòu)Queue的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09

最新評(píng)論

武夷山市| 惠东县| 沙雅县| 六安市| 通江县| 晴隆县| 松桃| 清远市| 陆丰市| 长葛市| 凤山县| 安龙县| 蒲江县| 宜春市| 南平市| 盐山县| 油尖旺区| 鲜城| 筠连县| 安阳市| 棋牌| 镇康县| 北海市| 色达县| 泰来县| 斗六市| 麻栗坡县| 天台县| 武隆县| 卫辉市| 西畴县| 濉溪县| 富蕴县| 滨海县| 玛纳斯县| 万安县| 揭阳市| 通州区| 舟山市| 渝中区| 伊宁县|