天天看點

淺談協程并發競争資源問題

淺談協程并發競争資源問題

我們在實際操作過程中,往往會遇到擁有多條協程并發的情況,那麼當多條協程并發時,協程之間是如何競争有限的資源的呢?本文将介紹有關内容。

我們先看一看本文執行個體代碼的主函數,兩條子協程,主協程3秒後結束。

func main() {
    go fun1()
    go fun2()

    time.Sleep(3 * time.Second)
}
           

再看看看兩條子協程分别是幹些什麼吧!

func fun1(){
    //周遊字元串的每一個字元
    for _,c:=range "就像老鼠愛大米"{
        //如果這裡使用Println的話,輸出的會是字元在字元集中的編号。
        //這裡f是format也就是格式的意思。
        fmt.Printf("%c\n",c)
        //runtime.Goexit()
        //每隔一納秒列印一個字。
        time.Sleep(time.Nanosecond)
    }

}

func fun2(){
    for _,c := range"ReganYue"{
        fmt.Printf("%c\n",c)
        //runtime.Goexit()
        time.Sleep(time.Nanosecond)

    }
}           

fun1函數,是周遊輸出"就像老鼠愛大米",值得注意的是,這裡使用for...range循環周遊字元串的話,不能使用

fmt.Println

,因為如果這裡使用

Println

的話,輸出的會是字元在字元集中的編号。

fmt.Printf

這裡f是format也就是格式化的意思。

看看運作結果

R
就
像
e
g
老
鼠
a
n
愛
Y
大
米
u
e           

發現兩條協程運作的結果均勻分布。這就說明兩條協程公平競争資源,兩條協程之間實力旗鼓相當。

可如果激活fun1内的

runtime.Goexit()

那麼輸出結果就是:

就
R
e
g
a
n
Y
u
e           

如果激活fun2内的

runtime.Goexit()

就
R
像
老
鼠
愛
大
米
           

因為

Goexit

殺掉它的 goroutine,其他 goroutine 也不會受到影響。是以當fun1的所在的子協程被殺死時,不會影響fun2所在的子協程的正常運作。

如果本段代碼中兩個

runtime.Goexit()

都激活,那麼兩條協程都隻會輸出一個字元。

就
R           

因為兩條協程在輸出完一個字元後就被殺死了。

如果兩個及以上個協程在沒有同步的情形下去通路共享的資源,并且嘗試同一時間讀和寫共享的資源。就會出現資源競争問題。出現的這個問題能夠讓程式變得稍微複雜,本文就暫時不讨論這些複雜情況,想知道的可以關注部落客,部落客後期會介紹。

我們也可以使用

go build

-race

參數,使用它可以了解是否存在資源競争問題,關于

go build

-race

參數的使用,本篇博文暫不介紹,後期部落客會盡量詳細介紹。