go语言:一个简单的goroutine同步,synchronize

我们可以使用channels在多个goroutine之间进行同步(synchronize), 下面直接看例子。

例子 1, 使用chan等待一个goroutine结束。

package main

import "fmt"
import "time"

//在这定义一个函数,以goroutine的方式运行。使用done这个chan来通知
//其它的函数本函数的工作已成。这个例子是通知main函数。
func worker(done chan bool) {
    fmt.Print("working...")
    for i:=0;i<10;i++ {
        time.Sleep(time.Second)
        fmt.Print(".")
    }
    fmt.Println("done")

    // 函数结束时,给chan赋值
    done <- true
}

func main() {

    // Start a worker goroutine, giving it the channel to
    // notify on.
    //启动一个goroutine并给传入一个chan
    c := make(chan bool, 1)
    go worker(c)

    // main函数在没有收到chan的值时会一直block.
    <-c //如果没有这句, mai函数会立即退出而不会等待worker
}

例子2, 函数B在 函数A结束后运行。

package main

import (
  "fmt"
  "time"
)
//定义函数A,以goroutine的方式运行
func workerA(done chan bool){
  fmt.Print("A is running")
  for i:=0;i<10;i++{
    fmt.Print(".")
    time.Sleep(1 * time.Second)
  }
  fmt.Println("done")

  done <- true
}

//定义函数B,以gortoutine的方式运行
func workerB(){
  fmt.Print("B is running")
  for i:=0;i<10;i++{
    fmt.Print(".")
    time.Sleep(1 * time.Second)
  }
  fmt.Println("done")
}

func main(){
  c:= make(chan bool, 1)
  //启动A,传入chan c
  go workerA(c)
    
  //只有A运行结束时,B才能运行
  select {
  case <-c:
    go workerB()
    //fmt.Println("B is done !")
  }
  
  // wait for workerB exit.
  // 为防止main函数在B之前退出,等待一段时间。
  time.Sleep(20*time.Second)
}