go语言学习笔记22------Go语言并发编程②

1.Goroutine

1.1什么是Goroutine

goroutine是Go语言并行设计的核心,有人称之为go程。 goroutine说到底其实就是协程,它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些goroutine之间的内存共享。执行goroutine只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩。也正因为如此,可同时运行成千上万个并发任务。goroutine比thread更易用、更高效、更轻便。
一般情况下,一个普通计算机跑几十个线程就有点负载过大了,但是同样的机器却可以轻松地让成百上千个goroutine进行资源竞争。

1.2Goroutine的创建

只需在函数调⽤语句前添加 go 关键字,就可创建并发执⾏单元。开发⼈员无需了解任何执⾏细节,调度器会自动将其安排到合适的系统线程上执行。
在并发编程中,我们通常想将一个过程切分成几块,然后让每个goroutine各自负责一块工作,当一个程序启动时,主函数在一个单独的goroutine中运行,我们叫它main goroutine。新的goroutine会用go语句来创建。而go语言的并发设计,让我们很轻松就可以达成这一目的。
示例:

package main

import (
   "fmt"
)

func task()  {
   i:=0
   for{
      i++
      fmt.Printf("new子go程正在打印,i=%d\n",i)

   }
}
func main()  {
go task()
   i:=0
   for{
      i++
      fmt.Printf("===========new主go程正在打印,i=%d\n",i)

   }
}
//输出结果
//===========new主go程正在打印,i=1
//new子go程正在打印,i=1
//new子go程正在打印,i=2
//===========new主go程正在打印,i=2
//new子go程正在打印,i=3
//===========new主go程正在打印,i=3
//===========new主go程正在打印,i=4
//new子go程正在打印,i=4
//new子go程正在打印,i=5
//===========new主go程正在打印,i=5
//===========new主go程正在打印,i=6
//new子go程正在打印,i=6
//new子go程正在打印,i=7
//===========new主go程正在打印,i=7
//===========new主go程正在打印,i=8
//new子go程正在打印,i=8
//new子go程正在打印,i=9
//===========new主go程正在打印,i=9
//===========new主go程正在打印,i=10
//new子go程正在打印,i=10
//new子go程正在打印,i=11
//===========new主go程正在打印,i=11
//......

1.3

Goroutine特性
主goroutine退出后,其它的工作goroutine也会自动退出:
实例如下:

package main

import (
   "fmt"
)

func task()  {
   i:=0
   for{
      i++
      fmt.Printf("new子go程正在打印,i=%d\n",i)

   }
}
func main()  {
go task()
      fmt.Print("===========new主go程正在打印")

}
//输出结果
//new子go程正在打印,i=1
//new子go程正在打印,i=2
//===========new主go程正在打印
//Process finished with exit code 0

2.runtime包

常用:runtime包
Gosched
runtime.Gosched() (go schedule)用于让出CPU时间片,让出当前goroutine的执行权限,调度器安排其他等待的任务运行,并在下次再获得cpu时间轮片的时候,从该出让cpu的位置恢复执行。
有点像跑接力赛,A跑了一会碰到代码runtime.Gosched() 就把接力棒交给B了,A歇着了,B继续跑。
示例代码:

package main

import (
   "fmt"
   "runtime"
)

func main() {
   go func(s string) {
      for i := 0; i < 5; i++ {
         fmt.Println(s)
      }
   }("hello")
   for i := 0; i < 3; i++ {
      runtime.Gosched()
      fmt.Println("world")
   }
}
//没有使用runtime.Gosched()时:
//hello
//hello
//hello
//world
//world
//world
//使用runtime.Gosched()时:
//hello
//hello
//hello
//hello
//world
//hello
//world
//world

以上程序的执行过程如下:
主协程进入main()函数,进行代码的执行。当执行到go func()匿名函数时,创建一个新的协程,开始执行匿名函数中的代码,主协程继续向下执行,执行到runtime.Gosched( )时会暂停向下执行,直到其它协程执行完后,再回到该位置,主协程继续向下执行。
Goexit
调用 runtime.Goexit() 将立即终止当前 goroutine 执⾏,调度器确保所有已注册 defer 延迟调用被执行。
示例代码:

package main

import (
   "fmt"
   "runtime"
)

func main() {
   go func() {
      fmt.Println("AAAAAA")
      func (){
         fmt.Println("BBBBBB")
         runtime.Goexit() // 终止当前 goroutine,以上会执行,以下不会执行
         fmt.Println("123456")
      }()
      fmt.Println("654321")
   }()
   //死循环,目的不让主goroutine结束
   for{
      ;
   }
}
//输出结果
//AAAAAA
//BBBBBB



猜你喜欢

转载自blog.csdn.net/weixin_42927934/article/details/82431789