1.WaitGroup等待目前運作的協程
package main
import (
"fmt"
"runtime"
"sync"
)
// Go語言的并發指的是能讓某個函數獨立于其他函數運作的能力
// Go的排程器是在作業系統之上的
//Go的并發同步模型來自一個叫做通信順序程序(CSP)的東西
//同步和傳遞資料的關鍵資料類型是通道
func main() {
// 配置設定一個邏輯處理器給排程器使用
runtime.GOMAXPROCS(1)
//wg用來等待程式完成
//計數加2,表示要等待2個goroutine
var wg sync.WaitGroup
wg.Add(2)
fmt.Println("Start Goroutines")
//聲明一個匿名函數,建立一個goroutine
go func() {
// 在函數退出時調用Done來同志main函數工作已經完成
defer wg.Done()
for count := 0; count < 3; count++ {
for char := 'a'; char < 'a'+26; char++ {
fmt.Printf("%c ", char)
}
}
}()
go func(){
defer wg.Done()
for count := 0; count < 3; count++ {
for char := 'A'; char < 'A'+26; char++ {
fmt.Printf("%c ", char)
}
}
}()
//等待goroutine結束
fmt.Println("Waiting To Finish")
wg.Wait()
fmt.Println("\nTerminating Program")
}
2.互斥鎖
在對共享資源進行計算的時候使用
package main
import (
"fmt"
"runtime"
"sync"
)
var (
// counter是所有goroutines都要增加其值的變量
counter int
// wg用來等待程式結束
wg sync.WaitGroup
// mutex用來定義一段代碼臨界區
mutex sync.Mutex
)
func main() {
// 計數為2,表示要等待兩個goroutines
wg.Add(2)
go incCounter(1)
go incCounter(2)
wg.Wait()
fmt.Printf("Final Counter: %d\n",counter)
}
func incCounter(id int){
defer wg.Done()
for count:=0;count<2;count++{
// 同一時刻隻允許一個goroutine進入
// 這個是臨界區
mutex.Lock()
{
//捕獲counter的值
value:=counter
// 目前goroutines從線程退出,并放回到隊列
runtime.Gosched()
//增加本地的value變量的值
value++
counter = value
}
mutex.Unlock()
//釋放鎖,允許其他正在等待的goroutine
//進入臨界區
}
}
mutex.Lock(){}的花括号隻是為了友善看,可以省略。
3.無緩沖通道的使用
package main
import (
"fmt"
"sync"
"time"
)
//var wg sync.WaitGroup
//
//func main() {
// // 建立一個無緩沖的通道
// baton := make(chan int)
//
// // 為最後一位跑步者将計數加1
// wg.Add(1)
// //第一位跑步者持有接力棒
// go Runner(baton)
// // 第一位選手接棒
// baton <- 1
// wg.Wait()
//
//}
//
//func Runner(baton chan int) {
// var newRunner int
// // 等待接力棒
// runner := <-baton
//
// // 開始繞着跑道跑步
// fmt.Printf("Runner %d Running With Baton\n", runner)
// if runner != 4 {
// newRunner = runner + 1
// fmt.Printf("Running %d To Rhe Line\n", newRunner)
// go Runner(baton)
// }
// time.Sleep(1000 * time.Millisecond)
// //比賽結束了麼
// if runner == 4 {
// fmt.Printf("Runner %d Finished,Race Over\n", runner)
// defer wg.Done()
// return
// }
// fmt.Printf("Runner %d Exchange with Runner %d\n", runner, newRunner)
// baton <- newRunner
//}
var wg sync.WaitGroup
func main() {
//建立一個無緩沖的通道
baton:=make(chan int)
wg.Add(1)
go Runner(baton) //第一位跑步者持有接力棒
baton<-1 //開始比賽
wg.Wait() //等待比賽結束
}
func Runner(baton chan int ){
var newRunner int
runner:=<-baton
fmt.Printf("第 %d 位選手開始跑\n",runner)
if runner!=4{
newRunner = runner+1
fmt.Printf("第 %d 位選手準備\n",runner)
go Runner(baton)
}
time.Sleep(1000*time.Millisecond)
if runner==4{
fmt.Printf("第%d位選手到達終點,比賽結束")
wg.Done() //完成的時候調用
}
//交給下一位
baton<-newRunner
}