果朗与时间同游

  • 本文关键字:时间 go goroutine
  • 更新时间 :
  • 英文 :


我正在学习Golang并编写一些示例程序以熟悉不同的概念。我写了这篇示例文章来了解go例程是如何工作的,并遇到了这个问题。我想不出这个程序出了什么问题。当generateAddRandomNumbers((和geneateEvenRandomNumber((中的最后一行被注释掉时,它可以完美地工作。

// time.Sleep(time.Duration(val))

当我在两个函数中取消注释该行时,输出总是错误的。

代码:

package main
import (
"fmt"
"math/rand"
"time"
)
const (
limit = 10000
)
func main() {
rand.Seed(time.Now().UnixNano())
go generateOddRandomNumbers(rand.Intn(9) + 1)
go generateEvenRandomNumbers(rand.Intn(9) + 1)
time.Sleep(1000000)
}
func generateOddRandomNumbers(count int) {
for i := 0; i < count; i++ {
val := rand.Intn(limit)
if val % 2 == 0 {
i--
continue
}
fmt.Printf("Odd[%v/%v] -> %vn", i + 1, count, val)
// time.Sleep(time.Duration(val))
}
}
func generateEvenRandomNumbers(count int) {
for i := 0; i < count; i++ {
val := rand.Intn(limit)
if val % 2 != 0 {
i--
continue
}
fmt.Printf("Even[%v/%v] -> %vn", i + 1, count, val)
// time.Sleep(time.Duration(val))
}
}

例如:输出良好:Even((从1/6打印到6/6,Odd((从1/3打印到3/3

Even[1/6] -> 5202
Even[2/6] -> 2768
Even[3/6] -> 3020
Even[4/6] -> 6386
Even[5/6] -> 8004
Odd[1/3] -> 5075
Odd[2/3] -> 8057
Odd[3/3] -> 9655
Even[6/6] -> 8886

错误的输出:(当time.Sleep((被取消注释时(在以下情况下,Even仅从1/9到3/9(与1/9到9/9相反(打印

Odd[1/1] -> 4349
Even[1/9] -> 6024
Even[2/9] -> 5444
Even[3/9] -> 6160

知道吗?

Go程序不会等待Go例程完成。
  • 如果在goroutine中注释time.Sleep,那么goroutine运行得很快,因此可以获得完整的输出。

  • 如果在goroutine中取消注释time.Sleep,则goroutine运行缓慢。一旦它产生了调度器,主go程序就会完成,所以你的goroutine就没有机会完成整个运行。

您可以使用channelsync.WaitGroup来同步您的过程,例如如何在Golang中等待所有goroutine完成。

顺便说一句,对于time.Sleep(1000000),它的单位是ns,所以在您的示例中,主go程序会快速退出。

程序退出的原因是因为主线程没有等待派生的goroutines完成。你必须保持主线程打开。

一种方法是使用WaitGroups

使用此示例的修改版本,您可以执行以下操作:

去游乐场

package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
const (
limit = 10000
)
func main() {
rand.Seed(time.Now().UnixNano())

var wg sync.WaitGroup
// Add our two items to the wait group
wg.Add(2)

// Call our two items
go generateOddRandomNumbers(rand.Intn(9) + 1, &wg)
go generateEvenRandomNumbers(rand.Intn(9) + 1, &wg)
// Wait for them
wg.Wait()
}
func generateOddRandomNumbers(count int, wg *sync.WaitGroup) {
defer wg.Done();
for i := 0; i < count; i++ {
val := rand.Intn(limit)
if val%2 == 0 {
i--
continue
}
fmt.Printf("Odd[%v/%v] -> %vn", i+1, count, val)
// time.Sleep(time.Duration(val))
}
}
func generateEvenRandomNumbers(count int, wg *sync.WaitGroup) {
defer wg.Done();
for i := 0; i < count; i++ {
val := rand.Intn(limit)
if val%2 != 0 {
i--
continue
}
fmt.Printf("Even[%v/%v] -> %vn", i+1, count, val)
// time.Sleep(time.Duration(val))
}
}
/** Which outputs:
Even[1/8] -> 2162
Even[2/8] -> 324
Even[3/8] -> 8388
Even[4/8] -> 7084
Even[5/8] -> 9282
Even[6/8] -> 302
Even[7/8] -> 6232
Even[8/8] -> 8384
Odd[1/3] -> 5063
Odd[2/3] -> 1239
Odd[3/3] -> 7947
*/

最新更新