Go语言中线程的同步

Synchronisation of threads in Go lang

我想更多地了解线程同步在 go 中的工作原理。下面是我的程序的一个功能版本,它使用一个完成的通道进行同步。

package main

import (
    . "fmt"
    "runtime"
)

func Goroutine1(i_chan chan int, done chan bool) {
    for x := 0; x < 1000000; x++ {
        i := <-i_chan
        i++
        i_chan <- i
    }
    done <- true
}
func Goroutine2(i_chan chan int, done chan bool) {
    for x := 0; x < 1000000; x++ {
        i := <-i_chan
        i--
        i_chan <- i
    }
    done <- true
}

func main() {
    i_chan := make(chan int, 1)
    done := make(chan bool, 2)
    i_chan <- 0

    runtime.GOMAXPROCS(runtime.NumCPU())
    go Goroutine1(i_chan, done)
    go Goroutine2(i_chan)
    <-done
    <-done
    Printf("This is the value of i:%d\n", <-i_chan)
}

然而,当我尝试 运行 它时没有任何同步。使用等待语句并且没有通道来指定何时完成,因此没有同步。

const MAX = 1000000

func Goroutine1(i_chan chan int) {
    for x := 0; x < MAX-23; x++ {
        i := <-i_chan
        i++
        i_chan <- i
    }
}

func main() {
    i_chan := make(chan int, 1)
    i_chan <- 0
    runtime.GOMAXPROCS(runtime.NumCPU())
    go Goroutine1(i_chan)
    go Goroutine2(i_chan)
    time.Sleep(100 * time.Millisecond)
    Printf("This is the value of i:%d\n", <-i_chan)
}

它会打印出错误的 i 值。如果你延长等待时间,比如说 1 秒,它就会完成并打印出正确的语句。我有点理解它有一些东西,在你打印 i_chan 上的内容之前,两个线程都没有完成我只是有点好奇这是如何工作的。

请注意,您的 first example would deadlock, since it never calls GoRoutine2(编辑问题后的 OP)。
如果it calls GoRoutine2, then the expected i value is indeed 0.

没有同步,(如in this example),不能保证main()在完成Goroutine1()之前不退出并且Goroutine2().
对于 1000000 次循环,1 毫秒的等待似乎就足够了,但同样不能保证。

func main() {
    i_chan := make(chan int, 1)
    i_chan <- 0
    runtime.GOMAXPROCS(runtime.NumCPU())
    go Goroutine2(i_chan)
    go Goroutine1(i_chan)
    time.Sleep(1 * time.Millisecond)
    Printf("This is the value of i:%d\n", <-i_chan)
}

在“How to Wait for All Goroutines to Finish Executing Before Continuing", where the canonical way is to use the sync package’s WaitGroup structure, as in this runnable example.

查看更多内容