天天看點

Go并發

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

}      

繼續閱讀