输出结果为什么是这样呢?

img


我想让他输出的是“结果=2”,但是为什么他的输出结果是这样的呢?

编码格式问题。把你的代码文件另存为,选择编码UTF-8

看看记事本默认的编码格式

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/226638
  • 这篇博客也不错, 你可以看下多线程(超过2个)轮流输出的多数问题
  • 除此之外, 这篇博客: 什么是协程?中的 (2)调度器的设计策略 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 复用线程:避免频繁的创建、销毁线程,而是对线程的复用。

    • 当本线程无可运行的 G 时,尝试从其他线程绑定的 P 偷取 G,而不是销毁线程。
    • 当本线程因为 G 进行系统调用阻塞时,线程释放绑定的 P,把 P 转移给其他空闲的线程执行。
    • 在 coroutine 中要等待一个协程主动让出 CPU 才执行下一个协程,在 Go 中,一个 goroutine 最多占用 CPU 10ms,防止其他 goroutine 被饿死,这就是 goroutine 不同于 coroutine 的一个地方。
    • 当 M 执行 work stealing 从其他 P 偷不到 G 时,它可以从全局 G 队列获取 G。

    一个协程的具体调度流程

    从上图我们可以分析出几个结论:

    ​ 1、我们通过 go func () 来创建一个 goroutine;

    ​ 2、有两个存储 G 的队列,一个是局部调度器 P 的本地队列、一个是全局 G 队列。新创建的 G 会先保存在 P 的本地队列中,如果 P 的本地队列已经满了就会保存在全局的队列中;

    ​ 3、G 只能运行在 M 中,一个 M 必须持有一个 P,M 与 P 是 1:1 的关系。M 会从 P 的本地队列弹出一个可执行状态的 G 来执行,如果 P 的本地队列为空,就会想其他的 MP 组合偷取一个可执行的 G 来执行;

    ​ 4、一个 M 调度 G 执行的过程是一个循环机制;

    ​ 5、当 M 执行某一个 G 时候如果发生了 syscall 或则其余阻塞操作,M 会阻塞,如果当前有一些 G 在执行,runtime 会把这个线程 M 从 P 中摘除 (detach),然后再创建一个新的操作系统的线程 (如果有空闲的线程可用就复用空闲线程) 来服务于这个 P;

    ​ 6、当 M 系统调用结束时候,这个 G 会尝试获取一个空闲的 P 执行,并放入到这个 P 的本地队列。如果获取不到 P,那么这个线程 M 变成休眠状态, 加入到空闲线程中,然后这个 G 会被放入全局队列中。