【问题标题】:Synchronisation of threads in Go langGo 语言中的线程同步
【发布时间】:2015-01-23 15:47:15
【问题描述】:

我想更多地了解线程同步在 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 上的内容之前,两个线程都没有完成,我只是有点好奇这是如何工作的。

【问题讨论】:

  • 您在第一个示例中是否错过了对Goroutine2 的呼叫?在您的第二个示例中,Goroutine2 的定义在哪里?您在第二个示例中提到了有关“等待语句”的内容——什么是“等待语句”,它在哪里?
  • 注意:Go 没有“线程”作为语言结构。你的意思是“goroutines”吗?
  • @BraveNewCurrency goroutines 是我对绿色线程的理解,因此您可以编写关键字 go 并启动一个新的绿色线程。对吗?
  • @Amit Kumar Gupta。是的,那里有一些复制意大利面错误。我现在确实修好了。通过等待语句,它是最后的睡眠语句。所以基本上它并没有真正等待任何事情完成它只是让主线程进入睡眠状态。

标签: multithreading go


【解决方案1】:

请注意,您的 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”查看更多信息,其中规范方法是使用sync package’s WaitGroup structure,如this runnable example

【讨论】:

    猜你喜欢
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多