淺談協程并發競争資源問題
我們在實際操作過程中,往往會遇到擁有多條協程并發的情況,那麼當多條協程并發時,協程之間是如何競争有限的資源的呢?本文将介紹有關内容。
我們先看一看本文執行個體代碼的主函數,兩條子協程,主協程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
參數的使用,本篇博文暫不介紹,後期部落客會盡量詳細介紹。