Live data from Hacker News

Singleton Pattern in Go

marcio.io

21–30 of 76 posts

Re: Singleton Pattern in Go

#21
post #2

It’s worth noting that not only do you need to synchronize access to the singleton, you need to synchronize access to the singleton’s state as well. And even if you manage that at a fine-grained layer, you’re still setting yourself up for all the problems associated with singletons: http://c2.com/cgi/wiki?SingletonsAreEvil . If you have a bunch of immutable state, then build unexported package variables in the packag…

Do you think it would be fine to use a singleton if the writes are all happening in a single thread and it's not critical that the reads be synchronized? Sharing state across go routines seems like something to be avoided. In vanilla Java it's always not easy to avoid sharing state.

Re: Singleton Pattern in Go

#22
post #6

I thought there was a lot of literature pretty convincingly arguing that singleton is in fact an anti-pattern.

Singletons are useful and wide spread concepts. What is an anti pattern is implementing them in a way that's not thread safe (which is made worse if your singleton is mutable).

Letting DI frameworks handle your singletons is the best way to get the best of both worlds.

Re: Singleton Pattern in Go

#23
post #21
post #2

It’s worth noting that not only do you need to synchronize access to the singleton, you need to synchronize access to the singleton’s state as well. And even if you manage that at a fine-grained layer, you’re still setting yourself up for all the problems associated with singletons: http://c2.com/cgi/wiki?SingletonsAreEvil . If you have a bunch of immutable state, then build unexported package variables in the packag…

Do you think it would be fine to use a singleton if the writes are all happening in a single thread and it's not critical that the reads be synchronized? Sharing state across go routines seems like something to be avoided. In vanilla Java it's always not easy to avoid sharing state.

If you want your reads to ever work, then they need to be synchronized. Reading from an unfenced address during concurrent writes is undefined behavior for any CPU architecture you can think of, which means you’ll get stale reads _in a best-case scenario_. You can also get garbage reads (e.g. as your CPU interprets your read of a 64-bit pointer as two 32-bit reads), crashes, bees, etc.

The code you write is either thread-safe, used in a single-threaded context, or a pinless grenade.

Re: Singleton Pattern in Go

#24
Coding Pro Tip: Instead of using the Singleton pattern, make one instance of your class at the start of your program and pass it around to its users.

Singletons are really just as bad as global variables. Why? Because they are global variables.

Re: Singleton Pattern in Go

#25
post #9

This post is chock-full of antipatterns. Both the singleton pattern and double checked locking should be avoided.

Yea it's easy enough to use dependency injection to satisfy these supposedly "global" requirements. About the only global state I can tolerate is read-only constants, but even then you are much better off with DI just because of testing.

DI is an antipattern.

Re: Singleton Pattern in Go

#26
post #18
post #4

Your "check-lock-check" code is probably broken (depending on the intricacies of Golang's memory model). If the compiler or CPU reorders any stores to the fields of "instance" after the assignment to "instance" itself, other threads could start working with a partially uninitialized object. Once() uses atomics on the fast path for a reason.

Totally! I was going to post the same thing. Double-checked locking is either impossible or really hard to get right, depending on the language and architecture's guarantees! If you must use a singleton, I'd really recommend doing the so-called "aggressive" approach, which should have really been named the "actually won't crash sometimes" approach.

On C++ if we're using a bool as the "check" and pthread_mutex_lock on a regular mutex would that work, or do we still need to hardcode fences?

(Asking because this pattern is used by libcxxabi code)

Re: Singleton Pattern in Go

#27
post #9

This post is chock-full of antipatterns. Both the singleton pattern and double checked locking should be avoided.

Yea it's easy enough to use dependency injection to satisfy these supposedly "global" requirements. About the only global state I can tolerate is read-only constants, but even then you are much better off with DI just because of testing.

How do handle configuration? Your program starts up, generates some settings, then those need to be shared across all threads to avoid incurring the cost of regenerating during every call to a function.

Re: Singleton Pattern in Go

#28
post #3

This is cute, but I think (someone will correct me if I'm wrong) that the real idiom is: things that would be singletons in Java are instead servers managing a channel in Golang.

The beauty of Go's channel design approach is how it isolates responsibilities. It's not just about synchronization. A great example is Rob Pike's lexer.

When passing singletons around, you are communicating with shared state. Sometimes, there is no way around it.

Re: Singleton Pattern in Go

#29
post #21
post #2

It’s worth noting that not only do you need to synchronize access to the singleton, you need to synchronize access to the singleton’s state as well. And even if you manage that at a fine-grained layer, you’re still setting yourself up for all the problems associated with singletons: http://c2.com/cgi/wiki?SingletonsAreEvil . If you have a bunch of immutable state, then build unexported package variables in the packag…

Do you think it would be fine to use a singleton if the writes are all happening in a single thread and it's not critical that the reads be synchronized? Sharing state across go routines seems like something to be avoided. In vanilla Java it's always not easy to avoid sharing state.

If you're only reading/writing from one thread, then locking/unlocking a mutex should have an extremely small overhead. So if you plan on having such a pattern available for use in multithreaded contexts, a mutex or some other thread-safe abstraction couldn't hurt.

Re: Singleton Pattern in Go

#30

Earlier quoted context omitted.

Yea it's easy enough to use dependency injection to satisfy these supposedly "global" requirements. About the only global state I can tolerate is read-only constants, but even then you are much better off with DI just because of testing.

DI is an antipattern.

What are better alternatives? Service locator?
Post reply on HN