What could Go wrong with a mutex
evilmartians.com
What could Go wrong with a mutex
1–10 of 59 posts
Re: What could Go wrong with a mutex
#2Re: What could Go wrong with a mutex
#3Any time you want to limit concurrency (e.g. by using a pool), my experience is that you have to think hard about the correct way to do that. This despite the fact that the underlying idea of a worker pool seems very innocent and easy to use. Read a few papers on the topic and you’ll see a variety of approaches. For example, if work blocks, do you give up the slot to other work? No easy answer!
Re: What could Go wrong with a mutex
#4Channels are vastly oversold given their actual suitability and worse still, add their own classes of race conditions (deadlocks) so you often fallback to using mutexes for those, hopefully rare, occasions you need to pass a shared stated. And once you're reliant on mutexes then you're really no better off than you were with any other language where threading is an afterthought.
The only real benefit Go brings is the ease of spinning new goroutines, but that can be a double edged sword if you don't understand how to manage them in the first place, and the green thread model making goroutines lightweight. Though even this isn't exactly unique to Go either.
I feel like this is one of Go's biggest weaknesses yet it seldom seems to get the same discussion generics and error handling (both of which are annoyances in specific edge cases but neither of which cause the same level of show stopper bugs).
Re: What could Go wrong with a mutex
#5If anyone is wondering why RW mutexes block new readers if there is a waiting writer, the reason is to prevent writer starvation: if, say, two threads continuously acquire and release read locks, there may never be a point in time in which no thread is holding a lock, and the writer is stuck waiting forever. Some mutexes can be configured to use read priority, but that is something that should only be done if it can be proven that starvation cannot happen.
This is a reminder that read locks do not absolve from being careful about what happens in the critical section; it should be made as small as possible no matter whether the lock is exclusive or shared.
Re: What could Go wrong with a mutex
#6Does anyone know if there's a similar tool for Rust? I've had a few times in the past where I'm trying to figure out why some async application using tokio is hanging and having a similar tool would be very helpful.
Re: What could Go wrong with a mutex
#7The goroutine-inspect tool they used looks really useful. Does anyone know if there's a similar tool for Rust? I've had a few times in the past where I'm trying to figure out why some async application using tokio is hanging and having a similar tool would be very helpful.
Re: What could Go wrong with a mutex
#8People talk about the lack of generics et al as being Go's downfall but personally what I've found to be the biggest annoyance is the very thing Go boasts to be good at: writing bug/race free multi-threaded code. Channels are vastly oversold given their actual suitability and worse still, add their own classes of race conditions (deadlocks) so you often fallback to using mutexes for those, hopefully rare, occasions y…
Re: What could Go wrong with a mutex
#9People talk about the lack of generics et al as being Go's downfall but personally what I've found to be the biggest annoyance is the very thing Go boasts to be good at: writing bug/race free multi-threaded code. Channels are vastly oversold given their actual suitability and worse still, add their own classes of race conditions (deadlocks) so you often fallback to using mutexes for those, hopefully rare, occasions y…
Is there a language where deadlocks are not possible ?
Re: What could Go wrong with a mutex
#10When you use defer to release the lock, the entirety of your function becomes the critical section. If you add another bit of code that needs the same lock, your program goes boom.
I've hit this same issue a few times when I write a new, naive HTTP handler function that needs concurrent map access, then throw apachebench at it before I commit (or k6 when it's in QA/staging).
All of my deadlocks have come from deferring the release of the lock coupled with calling another bit of code that (acquires a second lock) rather than explicitly releasing the lock as soon as I no longer need its protection.
I may still defer the release of a lock in very small functions but, now when I see it in code, it immediately sets off alarm bells to look a bit closer.