Live data from Hacker News

Singleton Pattern in Go

marcio.io

51–60 of 76 posts

Re: Singleton Pattern in Go

#51

Earlier quoted context omitted.

+1 for the aggressive approach, mutexes are very fast in go. I got curious and wrote a quick little benchmark test: $ cat bench_test.go package main import ( "sync" "testing" ) func BenchmarkMutex(b *testing.B) { var m sync.Mutex for n := 0; n A set of mutex.Lock() & .Unlock() calls takes only 24.0ns on average to complete. Thus it's possible to lock/unlock more than 41 million times per second on the puny 2011 MacBo…

This has no contention and is essentially a no-op? Or do I not understand go?

It is a no-op, but Golang's Plan 9-based compilers don't do much optimization, so they aren't able to eliminate it.

Re: Singleton Pattern in Go

#54
It's funny how you can take an obvious antipattern (global variables) and turn it into a pattern by giving it a cool new name like "Singleton". In this spirit, I propose "the ProgramCounterAmbulator" as a cool new name for "goto."

Actually, gotos are usually less harmful than globals. At least they don't interfere with unit testing the way globals tend to.

Re: Singleton Pattern in Go

#55
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.

In modern Java, it's easy enough if you've been shown the pattern. What's hard is understanding/discovering it from first principles.

Re: Singleton Pattern in Go

#56

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.

I'm not sure how... pass it around is 'better' than global scope. Meaning not sure what problems you're avoiding here. If the scope is a single thread, no problem. If it's accessed from multiple threads, you have problems whether it's a global, singleton, or passed by reference.

Not actually completely true, you can still have races in single threaded code. Consider two state variables that are effected by a shared variable. Not hard to have the two state variables in disagreement over the shape of the world.

Re: Singleton Pattern in Go

#57

Earlier quoted context omitted.

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 th…

There are exceptions to this rule--i.e. there are ways to not really be thread-safe but to have things work anyway--but they fall in the category of "you have to really, really know your CPU and be willing to write processor-specific code that just happens to work", so you can basically ignore them. My favorite is the libdispatch abuse of cpuid to flood the pipeline on Intel CPUs for this problem: https://www.mikeash…

An interesting exception is Lamport's Bakery:

https://en.m.wikipedia.org/wiki/Lamport%27s_bakery_algorithm

Thread safety without synchronisation primitives. I'm not sure it's ever actually a good idea to use it, though.

EDIT: unless you count a fence as a synchronisation primitive.

Re: Singleton Pattern in Go

#58

It's funny how you can take an obvious antipattern (global variables) and turn it into a pattern by giving it a cool new name like "Singleton". In this spirit, I propose "the ProgramCounterAmbulator" as a cool new name for "goto." Actually, gotos are usually less harmful than globals. At least they don't interfere with unit testing the way globals tend to.

No argument that Singletons make it difficult to unit test things but there are genuine cases where singletons are required: For instance, you don't want to end up creating multiple objects that read the configuration file, when one is enough. Or you certainly don't want to create too many objs that are heavy (like a cache that stores data heavy objects, or services, or god-objects (which are themselves an anti-pattern unavoidable in certain cases)).

At times, there's genuinely only a single entity of "x" that's available for use by the environment, like a security-policy, or access to standard-output, and so on...

Singletons are necessary evil, IMO.

Re: Global state: At some point the abstraction will have to leak. If you squint enough, nothing is truly isolated, and everything's sharing everything else with other binaries on any given system at some abstraction level or the other. This is more often the reason why security-exploits are theoretically possible despite isolation.

Re: Singleton Pattern in Go

#59

It's funny how you can take an obvious antipattern (global variables) and turn it into a pattern by giving it a cool new name like "Singleton". In this spirit, I propose "the ProgramCounterAmbulator" as a cool new name for "goto." Actually, gotos are usually less harmful than globals. At least they don't interfere with unit testing the way globals tend to.

No argument that Singletons make it difficult to unit test things but there are genuine cases where singletons are required: For instance, you don't want to end up creating multiple objects that read the configuration file, when one is enough. Or you certainly don't want to create too many objs that are heavy (like a cache that stores data heavy objects, or services, or god-objects (which are themselves an anti-patte…

I find that a better approach is to try and isolate pieces of code that needs access to specific resources, such as configuration files or standard output. Performing IO tasks, from every module in a code base, is an easy way to create very unmaintainable code.

Of course this is all a tradeoff with other code structuring ideals. Programming languages with Monads tend to be very good at isolating such things.

Re: Singleton Pattern in Go

#60

It's funny how you can take an obvious antipattern (global variables) and turn it into a pattern by giving it a cool new name like "Singleton". In this spirit, I propose "the ProgramCounterAmbulator" as a cool new name for "goto." Actually, gotos are usually less harmful than globals. At least they don't interfere with unit testing the way globals tend to.

Any discussion of Singletons is incomplete without https://sites.google.com/site/steveyegge2/singleton-consider...
Post reply on HN