Golang 协程

Golang 协程

协程的特点

  • 独立的栈空间
  • 共享程序堆空间
  • 调度由用户控制
  • 协程是轻量级的线程
  • 如果函数有返回值, 使用协程时, 返回值将被吞掉

案例

编写一个程序完成如下功能:

  1. 在主线程中,开启一个goroutine, 该协程每隔1秒输出“hello world”
  2. 在主线程中也每隔一秒输出“hello golang”, 输出10次
  3. 要求主线程和goroutine同时执行
func test(){
	for i := 0; i < 10; i++ {
		fmt.Println("hello world",i)
		time.Sleep(time.Second)
	}
}
func main() {
	go test()
	for i := 0; i < 10; i++ {
		fmt.Println("hello golang", i)
		time.Sleep(time.Second)
	}
}

主线程和协程的执行流程图

与Java中的线程不同,Java如果没有设置守护线程,main线程需要在其他线程结束后才会退出

获取cpu核数

func main() {
        //cp逻辑核数等同于Java中的Runtime.getRuntime().availableProcessors();
	cpu := runtime.NumCPU()
	fmt.Println(cpu)// 8
        //设置运行的逻辑cpu个数, 并返回先前的配置
        cpu = runtime.GOMAXPROCS(4)
        fmt.Println(cpu)// 8
}

Goshced

func main() {
   for i := 0; i < 5; i++ {
      go func(i int) {
         if i == 3 {
            //相当于Java的yield
            runtime.Gosched()
         }
         for j := 0; j < 10; j++ {
            fmt.Println("task", i,"====>", j)
         }
      }(i)
   }
   for true {

   }
}
/*~~~~~~~~~~~~~~~~~~~~~~*/
func main() {
	//协程还没有启动主线程就已经跑完for, i大概率为5
	for i := 0; i < 5; i++ {
		go func(num int) {
                        //闭包可以访问外部的内容
			if i == 3 {
				//相当于Java的yield
				runtime.Gosched()
			}
			for j := 0; j < 10; j++ {
				fmt.Println("task", i,"====>", j)
			}
		}(100)
	}
	for true {

	}
}

Goexit

func task(){
	for i := 0; i < 10; i++ {
		if i == 5 {
			//主动退出当前运行的协程
			runtime.Goexit()
		}
		fmt.Println(i)
	}
}
func main() {
	go task()
	for true {

	}
}

如果主线程主动退出, 子线程就会自己运行, 直到死锁

func task(){
	for i := 0; i < 10; i++ {
		fmt.Println("task",i)
	}
}
func main() {
	go task()
	for i := 0; i < 10; i++ {
		if i == 3 {
			runtime.Goexit // 主线程主动退出
		}
		fmt.Println("main",i)
	}
}
posted @ 2020-08-14 19:59  CyberPelican  阅读(285)  评论(0编辑  收藏  举报