如何按所需顺序打印数字

I found many tutorials in internet about mutex, then after i try to build my own sample. Look at my following code snippet.

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)

}

As output I've got only 10 but my target is to get 1, 2, 3, 4...10. How can I do that? Or my sample does not make any sense?

the problem is that the function closure is bound to the external scope variable i And i changes during the loop. When the routine executes (most likely after the loop finishes) the value of i is 10.

There are two way of solving this, the first one is to create a new variable on each loop:

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

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

or by passing the value directly to the function closure:

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)
}

Try :

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

Here is why.

Your example doesn't make sense. Simply write:

package main

import (
    "fmt"
)

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

Output:

0 1 2 3 4 5 6 7 8 9

After fixing the bugs in your program, it's easy to see that using goroutines won't provide an ordered result.

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()
}

Output:

1 0 5 6 2 7 8 9 3 4 

Playground:

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

As peterSO already pointed out, if you simply want to print in order, concurrency (Go routines) and mutexes aren't needed:

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

But, if you want to do some calculation concurrently, and then print the results in the desired order, you can solve it by using a channel and have the main routine take care of the printing in order, or by using a sync.Cond as in the example below:

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()
}

Output:

0 1 2 3 4 5 6 7 8 9 

Playground: http://play.golang.org/p/k7tUfKPRxW

I used sync.WaitGroup instead of time.Sleep(time.Second) to prevent main from exiting prematurely. It is not required for the sync.Cond solution though.