Understanding Go random number NewSource concurrency

Viewed 29

Go's random package has a function called NewSource that helps create a random number generator with a custom seed.

The comment on the source code mentions https://github.com/golang/go/blob/master/src/math/rand/rand.go#L41

// Unlike the default Source used by top-level functions, this source is not
// safe for concurrent use by multiple goroutines.

What I don't understand is

  1. Is the NewSource alone not safe for concurrent use ? OR
  2. Is the random number generator that is constructed out of this new source not safe for concurrent use as well ?

Example program

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

func main() {

    // NewSource NOT safe for concurrent use
    rng := rand.New(rand.NewSource(time.Now().Unix()))

    //is the random number generator rng safe for concurrent use
    //since the NewSource is used only during the instantiation
    //or is the seed being internally modified everytime rng generates a random number
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            fmt.Printf("random number is: %f \n", rng.Float64())
        }()
    }
    wg.Wait()

}
1 Answers

If you want/desire/need a random number generator that is safe for use by multiple goroutines, take a look at the question, How to create a thread-safe rand.Source?

Math/rand does contain such an implementation, lockedSource, but for some reason, it's not exported. It is just a thin wrapper that serializes access via a mutex (see rand.go, line 385)

Would be pretty easy to clone that for your own use.

Oh, look ... somebody already did that:

Related