go---go 语句及其执行规则

package main

import (
	"fmt"
)

func main() {
	for i := 0; i < 10; i++ {
		go func() {
			fmt.Println(i)
		}()
	}
}

不会打印任何内容:
在这里插入图片描述
当程序执行到一条 go 语句时,Go 语言运行时系统会试图从某个存放空闲的 goroutine 的队列中获取一个 goroutine,找不到时才会创建一个 goroutine。

然后 Go 语言运行时系统用该 goroutine 包装当前的 go 函数,再将该 goroutine 追加到存放某个可运行的 goroutine 队列中。

因此,go 函数的执行时间总是会滞后于所属的 go 语句的执行时间。

而 for 语句会以很快的速度执行完毕,但那 10 个包装了 go 函数的 gorouting 往往还没获得运行的机会。

一旦主 goroutine 中的代码执行完毕,当前的 Go 程序就会结束运行。

让主 goroutine 等待其它 goroutine

package main

import (
	"fmt"
)

func main() {
	num := 10

	// struct{} 代表既不不含任何字段也不拥有任何方法的空结构体类型
	// 仅仅把通道当作传递某种简单信号的介质时,struct{} 作为元素类型是最好的
	sign := make(chan struct{}, num)  // 通道长度与 goroutine 数量一致

	for i := 0; i < num; i++ {
		go func() {
			fmt.Println(i)
	
			// 发送表达式应该在 go 函数体的最后面
			// struct{} 的方法只有一个,即 struct{}{},占用的内存空间是 0 字节
			sign <- struct{}{}  
		}()
	}

	// 从通道接收元素值,接收的次数应当与 goroutine 数量一致
	for j := 0; j< num; j++ {
		<- sign
	}
}

在这里插入图片描述

让多个 goroutine 按既定的顺序运行

如何在使用 goroutine 的情况下,让上述打印的结果为 0 到 9?

package main

import (
	"fmt"
	"sync/atomic"
	"time"
)

func main() {
	var count uint32  // count 成为一个信号,总是下一个可以调用打印函数的 go 函数的序号

	trigger := func(i uint32, fn func()) {
		for {
			// 不断获取一个名叫 count 变量的值
			// 如果该值与参数 i 相等,则调用 fn 函数
			if n := atomic.LoadUint32(&count); n == i {
				fn()

				// 将 count 变量的值加 1
				// 因为 trigger 函数会被多个 goroutine 并发调用
				// count 并非本地变量,所以对它的操作会产生竞争条件
				atomic.AddUint32(&count, 1)

				// 显式退出当前循环
				break
			}

			// 如果该值与参数 i 不等
			// 让当前 goroutine 睡眠一个纳秒再进入下一个迭代
			time.Sleep(time.Nanosecond)
		}
	}

	for i := uint32(0); i < 10; i++ {
		// 接收一个参数
		go func(i uint32) {
			fn := func() {
				fmt.Println(i)
			}
			trigger(i, fn)
		}(i)  // 调用时将变量 i 的值传递进去
	}

	// 让主 goroutine 最后一个运行完毕
	trigger(10, func(){})
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值