goroutine(2) goroutine同步
1.查看cpu和设置
package main import ( "fmt" "runtime" ) func main(){ n := runtime.NumCPU() //查看物理机cpu数量 runtime.GOMAXPROCS(n) //设置使用多少cpu,也就是多少个p fmt.Println(n) //4 }
2.不同goroutine之间如何进行同步
出现问题场景:出现问题场景: 一个函数run()中包含多个goroutine函数并发,这些goroutine函数会生成中间文件, 被run()函数运行结束后的check()函数检查. 当goroutine并发时, 并不会阻塞run()的上下文, 可能导致的情况为run()函数执行完毕( 但其中的goroutine并发函数没有执行完毕 ), 导致check()函数执行失败.
所以我们需要一种操作, 直到当前所有goroutine执行完毕, 才进行下一步操作,所以需要 goroutine同步
1)全局变量和锁同步
package main import( "fmt" "time" ) func calc() { for i := 0; i < 1000; i++ { time.Sleep(time.Millisecond) } } func main() { start := time.Now().UnixNano() go calc() go calc() go calc() end := time.Now().UnixNano() fmt.Printf("finished, cost:%d ms\n", (end - start)/1000/1000) // finished,cost:0 ms }
上面的例子品输出的是0ms,因为每个goroutine并没有阻塞主函数main()的运行,主函数结束了,而其它goroutine可能还在运行,看下面的改变,利用全局变量来等待所有的goroutine执行完成
package main import( "fmt" "time" ) var iscomp [3]bool //设置全局变量 func calc(index int) { for i := 0; i < 1000; i++ { time.Sleep(time.Millisecond) } iscomp[index] = true } func main() { start := time.Now().UnixNano() go calc(0) //每启用一个,就改变量的值 go calc(1) go calc(2) for { //死循环 等待所有的goroutine执行完成 if iscomp[0] && iscomp[1] && iscomp[2] { break } time.Sleep(time.Millisecond) } end := time.Now().UnixNano() fmt.Printf("finished, cost:%d ms\n", (end - start)/1000/1000) //finished, cost:1080 ms }
go语言里提供了一个sync包来等待所有的goroutine执行完成,
package main import( "fmt" "time" "sync" ) // var iscomp [3]bool //设置全局变量 func calc(waitgroup *sync.WaitGroup) { for i := 0; i < 1000; i++ { time.Sleep(time.Millisecond) } waitgroup.Done() // iscomp[index] = true } func main() { var waitgroup sync.WaitGroup //申明一个变量 start := time.Now().UnixNano() waitgroup.Add(3) go calc(&waitgroup) go calc(&waitgroup) go calc(&waitgroup) //每启用一个,增加一个,或者改成以下代码: /* for i:= 0;i<3;i++{ waitgroup.Add(1) go calc(&waitgroup) } */ // for { //死循环 等待所有的goroutine执行完成 // if iscomp[0] && iscomp[1] && iscomp[2] { // break // } // time.Sleep(time.Millisecond) // } waitgroup.Wait() end := time.Now().UnixNano() fmt.Printf("finished, cost:%d ms\n", (end - start)/1000/1000) //finished, cost:1080 ms }
2)channel(看下一篇channel)