• <span id="rnpqh"><u id="rnpqh"></u></span>
    <span id="rnpqh"><meter id="rnpqh"></meter></span>

      <dfn id="rnpqh"></dfn>

    溫馨提示×

    Go語言中資源競爭問題怎么解決

    發布時間:2023-02-17 16:28:06 來源:億速云 閱讀:92 作者:iii 欄目:編程語言

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

    場景

    我們現在需要對1~100求他們的階乘,并將結果放到一個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
        ...
    }

    代碼實現

    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語言中資源競爭問題怎么解決

    上述代碼執行結果其實是沒問題的,為什么會出現亂序呢?因為這是go語言中map其實就是亂序的,按照我們的理解,先存的先出,但是不好意思,Golang的map不是這樣的。 上面執行也沒什么問題啊,細心的同學可能發現了,這個版本的代碼并沒有用上并發,對吧。好接下來我們繼續改進

    并發實現

    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語言中資源競爭問題怎么解決我們可以發現,并發版就是在調用計算階乘函數的前面加上了一個go而已。不要小看這個go,扯遠了,當然大家知道這是go語言中開啟一個協程的關鍵字即可。

    執行結果就是,控制臺啥都沒輸出,這是因為主協程和子協程之間的執行關系,下面我們畫圖理解

    Go語言中資源競爭問題怎么解決

    從上圖中我們可以發現,主協程執行的時間短(表現在比較短),子協程執行時間比較長(表現在比較長) 我們一定要記住,子協程是相對于當前的主協程來說的,如果主協程不存在了,那就沒有子協程了

    所以上面代碼啥都沒輸出就是因為,主協程已經執行完了,但是子協程還沒做完,那子協程都沒做完,factorialMap中能有東西嗎?

    主等子

    這就引出我們第一個問題,主協程如何等待子協程執行完再退出程序。我們現在用一個最簡單,最容易想到的做法

    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語言中資源競爭問題怎么解決當并發數比較小的時候,這個問題可能不會出現,一旦并發數變大,問題就立馬出現了

    圖中的執行結果是并發map寫入錯誤為什么會出現這個問題,我們假設100個人往一個籃子里放水果,很容易。但是100個人從一個籃子里拿水果,那就會出問題,首先,籃子里的水果不一定夠100個,其二每個人都想先拿,必然會引起爭搶。

    問題一優化

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

    Go語言中資源競爭問題怎么解決

    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() // 執行完解鎖
        // }()
        lock.Lock() // 執行時上鎖
        factorialMap[n] = result
        lock.Unlock() // 執行后解鎖
    }
    
    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語言中資源競爭問題怎么解決執行結果有0可能是數據類型存不下了導致的,這個大家不用關心

    Go語言中資源競爭問題怎么解決這樣我們就解決了資源競爭的問題了。但其實還有一個問題,就是我們在主協程中還是必須手動等待,這要非常不好,那如果子協程3秒內解決不了怎么辦?

    問題二優化

    這個問題是我們不想在主協程中手動等待子協程,換句話說是我們不想直接在代碼中寫明要等待多長時間

    這里我們就引入了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() // 執行時上鎖
        factorialMap[n] = result
        lock.Unlock() // 執行后解鎖
        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的內部原理大家自己細扣,我這就不講了 總結來說就是WaitGroup是一個籃子,每開一個協程,就往籃子中加一個標識(Add函數),每執行完一個協程,就從籃子中減去一個標識(Done函數),最后查看籃子中,如果是空的,就表示協程執行完了(Wait函數)。

    以上就是關于“Go語言中資源競爭問題怎么解決”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    主題地圖

    国产精品国产精品一区精品国产自在现偷99精品国产在热2019国产拍偷精品网国产精品视频全国免费观看,国产精品v欧美精品v日韩精品青青精品视频国产久久国产精品久久精品国产亚洲精品国产精品国产欧美精品一区二区三区,国产精品第一页国产亚洲精品国产福利国产精品自拍国产精品视频在线观看亚洲国产精品一区二区久久国产精品国产三级国产专不,国产精品视频大陆精大陆国产国语精品2019精品国产品对白在线290年香蕉精品国产高清自在自线隔壁老王国产在线精品在线观看精品国产福利片,国产三级精品三级在专区精品国产自在现偷国产精品一区二区三区国产日韩精品欧美一区喷水亚洲精品国产精品国自产国产在线精品一区二区不卡