Why is my supposedly parallel go program not paral

2019-09-16 20:40发布

package main

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

var wg sync.WaitGroup

func alphabets() {
    for char := 'a'; char < 'a'+26; char++ {
        fmt.Printf("%c ", char)
    }
    wg.Done() //decrement number of goroutines to wait for
}

func numbers() {
    for number := 1; number < 27; number++ {
        fmt.Printf("%d ", number)
    }
    wg.Done()
}

func main() {
    runtime.GOMAXPROCS(2)
    wg.Add(2) //wait for two goroutines

    fmt.Println("Starting Go Routines")
    go alphabets()
    go numbers()

    fmt.Println("\nWaiting To Finish")

    wg.Wait() //wait for the two goroutines to finish executing

    fmt.Println("\nTerminating Program")
}

I expect the output to be mixed up(for lack of a better word), but instead; a sample output is:

$ go run parallel_prog.go

Starting Go Routines Waiting To Finish a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Terminating Program

What I'm I missing?

Thanks,

2条回答
Fickle 薄情
2楼-- · 2019-09-16 21:08

Are you using the Go playground by any chance? When I run your code locally, I get:

Starting Go Routines

Waiting To Finish
1 2 3 4 5 6 7 8 9 10 11 12 a 13 14 15 16 17 b 18 19 c 20 21 d 22 23 e 24 25 f 26 g h i j k l m n o p q r s t u v w x y z 
Terminating Program

The playground is deterministic in nature. Goroutines don't yield as often and don't run in multiple threads.

查看更多
成全新的幸福
3楼-- · 2019-09-16 21:17

You're missing nothing. It's working. The calls aren't showing up "interlaced" (mixed up) not because they're not being parallelized, but because they're happening really fast.

You can easily add some calls to time.Sleep to see the parallelization better. By sleeping, we know 100% that printing alphabets and numbers should be interlaced.

Your program with Sleep calls to "force" interlacing

package main

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

var wg sync.WaitGroup

func alphabets() {
    defer wg.Done()
    for char := 'a'; char < 'a'+26; char++ {
        fmt.Printf("%c ", char)
        time.Sleep(time.Second * 2)
    }
}

func numbers() {
    defer wg.Done()
    for number := 1; number < 27; number++ {
        fmt.Printf("%d ", number)
        time.Sleep(time.Second * 3)
    }    
}

func main() {
    fmt.Println("Starting Go Routines")
    wg.Add(2)
    go alphabets()
    go numbers()

    fmt.Println("\nWaiting To Finish")
    wg.Wait()
    fmt.Println("\nTerminating Program")
}

Note

You probably already know this, but setting GOMAXPROCS doesn't have any effect on whether or not this example is executed in parallel, just how many resources it consumes.

The GOMAXPROCS setting controls how many operating systems threads attempt to execute code simultaneously. For example, if GOMAXPROCS is 4, then the program will only execute code on 4 operating system threads at once, even if there are 1000 goroutines. The limit does not count threads blocked in system calls such as I/O.

Source: Go 1.5 GOMAXPROCS Default

查看更多
登录 后发表回答