Komu
Komu

Reputation: 14998

Why is my supposedly parallel go program not parallel

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,

Upvotes: 0

Views: 356

Answers (2)

Ezra
Ezra

Reputation: 7702

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

Upvotes: 6

Stephen Weinberg
Stephen Weinberg

Reputation: 53398

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.

Upvotes: 3

Related Questions