top | item 9873930

(no title)

codahale | 10 years ago

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 package’s `init` func and export funcs which use those variables.

If you have a bunch of mutable state, then don’t use a singleton.

discuss

order

lemevi|10 years ago

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.

codahale|10 years ago

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.

doomrobo|10 years ago

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.

eloff|10 years ago

You would have to use sync.Atomic for all reads and writes. If you just use normal reads and writes it's in violation of the Go language memory model. It might work for now or it might start a nuclear war. You never know.