Description
https://github.com/prometheus/client_golang/blob/main/prometheus/counter.go#L137
Technically speaking there is no data race here. But if there are many threads trying to update the same counter, I can imagine that this never makes progress. Is it worth it to add a mechanism similar to Solaris' adaptive lock here? (Start from spinlock and after a time sleep on a lock?)
The impl here could be to loop some number of times, say 256, and then start sleeping a random amount of time between each loop. It's simple. The downside is that if the threads are stacking up then new threads -- that haven't reached the 256 limit yet -- will get serviced first and long-waiting threads get starved out. So to prevent that we add an atomic which is the number of waiters (anyone over 256 that is in the delayed loop) and if that is non-zero on entry then new threads also queue up right away. There's still some random factor and they aren't serviced in strict order but there's more fairness.
Same goes for Gauge.Add()
.
I haven't experienced any problem myself. I was just looking into the thread safety as I decided I want to call Add()
concurrently in my program. So I mean if no one has ever complained about this it might not be worth any effort.