为什么最后一个戈鲁廷首先在循环中以两个戈鲁廷开始?

我一直在用goroutines做一些测试,我注意到一个奇怪的行为(对我来说)使用这个代码:


游乐场: https://play.golang.org/p/Py4oqGqkYKm


package main


import (

    "fmt"

    "sync"

)

var (

    mu sync.Mutex

    wg sync.WaitGroup

)


func main() {

    var x int

    for i := 0; i < 10; i++ {

        wg.Add(2)

        go func() {

            mu.Lock()

            x = i

            mu.Unlock()

            wg.Done()

        }()

        go func() {

            mu.Lock()

            fmt.Print("x: ", x, " \n")

            mu.Unlock()

            wg.Done()

        }()

        wg.Wait()

    }

}

我期望输出如下:


x: 0 

x: 1 

x: 2 

x: 3 

x: 4 

x: 5 

x: 6 

x: 7 

x: 8 

x: 9 

但我收到了:


x: 0 

x: 0 

x: 1 

x: 2 

x: 3 

x: 4 

x: 5 

x: 6 

x: 7 

x: 8 

看起来第二个戈鲁廷被称为第一个(如后进先出)。想到这一点,我试图反转戈鲁廷,我得到了我所期望的答案:


游乐场: https://play.golang.org/p/BC1r3NK6RBm


package main


import (

    "fmt"

    "sync"

)


var (

    mu sync.Mutex

    wg sync.WaitGroup

)


func main() {

    var x int

    for i := 0; i < 10; i++ {

        wg.Add(2)

        go func() {

            mu.Lock()

            fmt.Print("x: ", x, " \n")

            mu.Unlock()

            wg.Done()

        }()

        go func() {

            mu.Lock()

            x = i

            mu.Unlock()

            wg.Done()

        }()

        wg.Wait()

    }

}

输出:


x: 0 

x: 1 

x: 2 

x: 3 

x: 4 

x: 5 

x: 6 

x: 7 

x: 8 

x: 9 

任何人都可以帮助我理解这种行为吗?


转到版本:go version go1.16.2 linux/amd64


慕姐4208626
浏览 69回答 2
2回答

SMILET

Go 语言不指定 goroutine 在显式同步之外使用通道、互斥锁、等待组等执行的顺序。该规范允许两个程序的两个输出。您正在观察互斥体的获取顺序,而不是戈鲁丁开始的顺序。可能是大肠按预期的顺序开始,但意外的大肠首先调用 Lock()。该程序确保的唯一排序是通过等待组:每对戈鲁丁将在下一对开始之前完成。

一只名叫tom的猫

Go 例程提供并发性,并在具有独立堆栈内存的共享堆分配之上工作。它们的目的是在多核系统之上提供并发执行。它们如何并行执行没有任何支配因素。这由实际的处理器决定。我们只通过抽象层使用处理器。实际上,没有并发系统可以管理/预测结果。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go