Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is uuid.NewV4() thread safe? #81

Closed
thanhps42 opened this issue Jun 27, 2018 · 2 comments
Closed

Is uuid.NewV4() thread safe? #81

thanhps42 opened this issue Jun 27, 2018 · 2 comments

Comments

@thanhps42
Copy link

When I call uuid.NewV4() in multiple goroutine, I have some question:

  • thread-safe?
  • Can I get same uuid when multiple goroutine call it at same time?
    P/s: sorry for my bad English

Thanks.

@brobits
Copy link

brobits commented Jul 6, 2018

I don't believe uuid.NewV4() is thread safe. here's the source for NewV4():

func (g *rfc4122Generator) NewV4() (UUID, error) {
	u := UUID{}
	if _, err := g.rand.Read(u[:]); err != nil {
		return Nil, err
	}
	u.SetVersion(V4)
	u.SetVariant(VariantRFC4122)

	return u, nil
}

the rfc4122Generator struct is global. the rand member (io.Reader) is not protected by any sort of mutex, and io.Readers just read from a raw byte buffer.

you could wrap NewV4() to be thread safe, something like:

var uuidGenerator sync.Mutex
func NewV4() (uuid.UUID, error) {
  uuidGenerator.Lock()
  defer uuidGenerator.Unlock()
  return uuid.NewV4()
}

although using goroutines to generate UUIDs, perhaps using channels to queue requests & responses is the more idiomatic go way.

@metaleap
Copy link

metaleap commented Jul 6, 2018

Globals and thread-safety are only of concern if there are writes happening to the global (or more specifically, to some piece of shared data, globally-scoped-or-not) concurrently with reads. (Ie. a "global" or shared var that's read-only throughout run time after some initial writes at init time is fully benign.) Not seeing such a situation here: a never-EOF'ing read-only rand reader should be "safeish" to a first intuition to begin with. What sort of state might it have to protect, really? But to verify our first intuition, we check the linux/unix/bsd/plan9 impl and lookie, there is seemingly a mutex on the underlying /dev/rand-consuming io.Reader anyway! see https://golang.org/src/crypto/rand/rand_unix.go --- so another locking/sync on top of it would buy nothing (but cost extra).

Haven't checked the Win impl, but the stdlib authors should surely be consistent in the locking/synchronization semantics of impls across OSes here. Anyone concerned can skim over the sources just as easily as I demo'd above 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants