Go語言中資源競(jìng)爭(zhēng)問題怎么解決

這篇“Go語言中資源競(jìng)爭(zhēng)問題怎么解決”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Go語言中資源競(jìng)爭(zhēng)問題怎么解決”文章吧。

創(chuàng)新互聯(lián)公司主要從事成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)城關(guān),十多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):028-86922220

場(chǎng)景

我們現(xiàn)在需要對(duì)1~100求他們的階乘,并將結(jié)果放到一個(gè)map中

1! = 1 = 1
2! = 1 * 2 = 2
3! = 1 * 2 * 3 = 6
4! = 1 * 2 * 3 * 4 = 24
5! = 1 * 2 * 3 * 4 * 5 = 120
...
{
    1: 1
    2: 2
    3: 6
    4: 24
    5: 120
    ...
}

代碼實(shí)現(xiàn)

var factorialMap = make(map[int]int)

func Factorial(n int) {
    result := 1
    for i := 1; i <= n; i++ {
        result *= i
    }
    factorialMap[n] = result
}

func main() {
    for i := 1; i < 10; i++ {
        Factorial(i)
    }
    for k, v := range factorialMap {
        fmt.Printf("%d 的階乘是%d\n", k, v)
    }
}

Go語言中資源競(jìng)爭(zhēng)問題怎么解決

上述代碼執(zhí)行結(jié)果其實(shí)是沒問題的,為什么會(huì)出現(xiàn)亂序呢?因?yàn)檫@是go語言中map其實(shí)就是亂序的,按照我們的理解,先存的先出,但是不好意思,Golang的map不是這樣的。 上面執(zhí)行也沒什么問題啊,細(xì)心的同學(xué)可能發(fā)現(xiàn)了,這個(gè)版本的代碼并沒有用上并發(fā),對(duì)吧。好接下來我們繼續(xù)改進(jìn)

并發(fā)實(shí)現(xiàn)

var factorialMap = make(map[int]int)

func Factorial(n int) {
    result := 1
    for i := 1; i <= n; i++ {
        result *= i
    }
    factorialMap[n] = result
}

func main() {
    for i := 1; i < 10; i++ {
        go Factorial(i)
    }
    for k, v := range factorialMap {
        fmt.Printf("%d 的階乘是%d\n", k, v)
    }
}

Go語言中資源競(jìng)爭(zhēng)問題怎么解決我們可以發(fā)現(xiàn),并發(fā)版就是在調(diào)用計(jì)算階乘函數(shù)的前面加上了一個(gè)go而已。不要小看這個(gè)go,扯遠(yuǎn)了,當(dāng)然大家知道這是go語言中開啟一個(gè)協(xié)程的關(guān)鍵字即可。

執(zhí)行結(jié)果就是,控制臺(tái)啥都沒輸出,這是因?yàn)橹鲄f(xié)程和子協(xié)程之間的執(zhí)行關(guān)系,下面我們畫圖理解

Go語言中資源競(jìng)爭(zhēng)問題怎么解決

從上圖中我們可以發(fā)現(xiàn),主協(xié)程執(zhí)行的時(shí)間短(表現(xiàn)在比較短),子協(xié)程執(zhí)行時(shí)間比較長(zhǎng)(表現(xiàn)在比較長(zhǎng)) 我們一定要記住,子協(xié)程是相對(duì)于當(dāng)前的主協(xié)程來說的,如果主協(xié)程不存在了,那就沒有子協(xié)程了

所以上面代碼啥都沒輸出就是因?yàn)?,主協(xié)程已經(jīng)執(zhí)行完了,但是子協(xié)程還沒做完,那子協(xié)程都沒做完,factorialMap中能有東西嗎?

主等子

這就引出我們第一個(gè)問題,主協(xié)程如何等待子協(xié)程執(zhí)行完再退出程序。我們現(xiàn)在用一個(gè)最簡(jiǎn)單,最容易想到的做法

var factorialMap = make(map[int]int)

func Factorial(n int) {
    result := 1
    for i := 1; i <= n; i++ {
        result *= i
    }
    factorialMap[n] = result
}

func main() {
    for i := 1; i < 100; i++ {
        go Factorial(i)
    }
    time.Sleep(time.Second * 3)
    for k, v := range factorialMap {
        fmt.Printf("%d 的階乘是%d\n", k, v)
    }
}

Go語言中資源競(jìng)爭(zhēng)問題怎么解決當(dāng)并發(fā)數(shù)比較小的時(shí)候,這個(gè)問題可能不會(huì)出現(xiàn),一旦并發(fā)數(shù)變大,問題就立馬出現(xiàn)了

圖中的執(zhí)行結(jié)果是并發(fā)map寫入錯(cuò)誤為什么會(huì)出現(xiàn)這個(gè)問題,我們假設(shè)100個(gè)人往一個(gè)籃子里放水果,很容易。但是100個(gè)人從一個(gè)籃子里拿水果,那就會(huì)出問題,首先,籃子里的水果不一定夠100個(gè),其二每個(gè)人都想先拿,必然會(huì)引起爭(zhēng)搶。

問題一優(yōu)化

針對(duì)上面的問題,我們引入全局鎖的概念。這就有點(diǎn)像我們上廁所,100個(gè)人都想上廁所,但廁所只有1個(gè),誰先搶到了誰先上,并且這個(gè)人還有給廁所上鎖,防止其他人進(jìn)來

Go語言中資源競(jìng)爭(zhēng)問題怎么解決

var factorialMap = make(map[int]int)
var lock sync.Mutex

func Factorial(n int) {
    result := 1
    for i := 1; i <= n; i++ {
            result *= i
    }
    // defer 不好理解
    // defer func(){
    // 	lock.Unlock() // 執(zhí)行完解鎖
    // }()
    lock.Lock() // 執(zhí)行時(shí)上鎖
    factorialMap[n] = result
    lock.Unlock() // 執(zhí)行后解鎖
}

func main() {
    for i := 1; i < 100; i++ {
        go Factorial(i)
    }
    time.Sleep(time.Second * 3)
    for k, v := range factorialMap {
        fmt.Printf("%d 的階乘是%d\n", k, v)
    }
}

Go語言中資源競(jìng)爭(zhēng)問題怎么解決執(zhí)行結(jié)果有0可能是數(shù)據(jù)類型存不下了導(dǎo)致的,這個(gè)大家不用關(guān)心

Go語言中資源競(jìng)爭(zhēng)問題怎么解決這樣我們就解決了資源競(jìng)爭(zhēng)的問題了。但其實(shí)還有一個(gè)問題,就是我們?cè)谥鲄f(xié)程中還是必須手動(dòng)等待,這要非常不好,那如果子協(xié)程3秒內(nèi)解決不了怎么辦?

問題二優(yōu)化

這個(gè)問題是我們不想在主協(xié)程中手動(dòng)等待子協(xié)程,換句話說是我們不想直接在代碼中寫明要等待多長(zhǎng)時(shí)間

這里我們就引入了WaitGroup

var factorialMap = make(map[int]int)
var lock sync.Mutex
var wg sync.WaitGroup

func Factorial(n int) {
    result := 1
    for i := 1; i <= n; i++ {
        result *= i
    }
    lock.Lock() // 執(zhí)行時(shí)上鎖
    factorialMap[n] = result
    lock.Unlock() // 執(zhí)行后解鎖
    wg.Done()
}

func main() {
    for i := 1; i < 100; i++ {
        wg.Add(1)
        go Factorial(i)
    }
    wg.Wait()
    for k, v := range factorialMap {
        fmt.Printf("%d 的階乘是%d\n", k, v)
    }
}

WaitGroup的內(nèi)部原理大家自己細(xì)扣,我這就不講了 總結(jié)來說就是WaitGroup是一個(gè)籃子,每開一個(gè)協(xié)程,就往籃子中加一個(gè)標(biāo)識(shí)(Add函數(shù)),每執(zhí)行完一個(gè)協(xié)程,就從籃子中減去一個(gè)標(biāo)識(shí)(Done函數(shù)),最后查看籃子中,如果是空的,就表示協(xié)程執(zhí)行完了(Wait函數(shù))。

以上就是關(guān)于“Go語言中資源競(jìng)爭(zhēng)問題怎么解決”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)頁題目:Go語言中資源競(jìng)爭(zhēng)問題怎么解決
標(biāo)題路徑:http://bm7419.com/article18/pssegp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、面包屑導(dǎo)航、品牌網(wǎng)站建設(shè)、域名注冊(cè)、品牌網(wǎng)站制作、電子商務(wù)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化