如何按所需顺序打印数字

时间:2014-09-02 17:32:16

标签: go

我在互联网上发现了许多关于互斥的教程,然后我尝试构建自己的样本。请查看以下代码段。

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {

    thread := new(sync.Mutex)
    y := 0

    for i := 0; i < 10; i++ {
        go func() {
            y = i
            thread.Lock()
            fmt.Println(y)
            thread.Unlock()
        }()
    }

    time.Sleep(100000)

}

作为输出我只有10但我的目标是获得1,2,3,4 ...... 10。我怎样才能做到这一点?或者我的样本没有任何意义?

4 个答案:

答案 0 :(得分:2)

问题是函数闭包绑定到外部作用域变量i 并且i在循环期间发生了变化。例程执行时(很可能在循环结束后)i的值为10。

有两种解决方法,第一种是在每个循环上创建一个新变量:

http://play.golang.org/p/ylTENWeuEl

for i := 0; i < 10; i++ {
    y := i
    go func() {
        thread.Lock()
        fmt.Println(y)
        thread.Unlock()
    }()
}

或将值直接传递给函数闭包:

http://play.golang.org/p/DKd12-VNSk

for i := 0; i < 10; i++ {
    go func(value int) {
        thread.Lock()
        fmt.Println(value)
        thread.Unlock()
    }(i)
}

答案 1 :(得分:2)

你的例子没有意义。只需写下:

package main

import (
    "fmt"
)

func main() {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }
    fmt.Println()
}

输出:

0 1 2 3 4 5 6 7 8 9

修复程序中的错误后,很容易看出使用goroutines不能提供有序的结果。

package main

import (
    "fmt"
    "runtime"
    "sync"
    "time"
)

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU() + 2)
    thread := new(sync.Mutex)
    for i := 0; i < 10; i++ {
        y := i
        go func() {
            thread.Lock()
            fmt.Print(y, " ")
            thread.Unlock()
        }()
    }
    time.Sleep(time.Second)
    fmt.Println()
}

输出:

1 0 5 6 2 7 8 9 3 4 

游乐场:

http://play.golang.org/p/FQdrL3z-hR

答案 2 :(得分:1)

尝试:

for i := 0; i < 10; i++ {
    go func(j int) {
        thread.Lock()
        fmt.Println(j)
        thread.Unlock()
    }(i)
}

这是why

答案 3 :(得分:1)

正如peterSO已经指出的那样,如果你只是想按顺序打印,则不需要并发(Go例程)和互斥量:

for i := 0; i < 10; i++ {
        fmt.Println(i)
}

但是,如果你想同时进行一些计算,然后按照所需的顺序打印结果,你可以通过使用一个通道解决它并让主程序按顺序处理打印,或者使用{ {1}}如下例所示:

sync.Cond

<强>输出:

package main

import (
    "fmt"
    "sync"
    "time"
)
func main() {

    var wg sync.WaitGroup

    c := sync.NewCond(new(sync.Mutex))
    var printed int

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(y int) {
            // Do some costly calculation that cakes y*y%10 milliseconds
            time.Sleep(time.Duration(y*y%10) * time.Millisecond)

            c.L.Lock()
            // Wait in a loop til it is this goroutine's turn
            for printed != y {
                c.Wait()
            }
            fmt.Printf("%d ", y)
            printed++
            c.L.Unlock()

            // Tell the waiting routines to check if it is their turn
            c.Broadcast()
            wg.Done()
        }(i)
    }

    wg.Wait()
}

游乐场: http://play.golang.org/p/k7tUfKPRxW

我使用0 1 2 3 4 5 6 7 8 9 代替sync.WaitGroup来防止主要过早退出。但time.Sleep(time.Second)解决方案并不需要它。