Comment by dwohnitmok

3 years ago

I find this to be an unfortunate state of affairs. If Clojure's STM was more developer-ergonomic, it could be used in a wide variety of places.

For example right now in Clojure, when you have concurrent access to a map, you're forced to choose between either atomic, but entirely serial writes (wrap the map in an atom) or per-key concurrency, but no inter-key atomicity (either use nested atoms or use ConcurrentHashMap).

But this false dilemma has all the hallmarks of complection. It's an all-or-nothing choice brought on by an overly coarse idea of atomicity. You could instead use a map structure built on top of STM to get exactly the amount of atomicity you need. If you need two keys to be modified in the same transaction then they get modified atomically. If you need another key to be modified in parallel, then that can happen. The amount of atomicity you need is specified dynamically and on the fly, instead of bound inextricably to a predetermined choice.

I find myself wishing for this kind of tool whenever I have concurrent write contention on a map. Yes I usually bite the bullet and just accept forced serial writes to an atom, but I do so begrudgingly.

Other ecosystems with more ergonomic STM systems use this to great effect (e.g. Haskell's stm-containers library: https://hackage.haskell.org/package/stm-containers).

> or per-key concurrency, but no inter-key atomicity (either use nested atoms or use ConcurrentHashMap).

I guess it depends upon what you mean by "per key", but if your map is a ref, and the values are refs, you can get per-value concurrency with inter-value atomicity.

You couldn't concurrently add new keys though, since that's changing the map's ref.

I’ve seen a Clojure library that does proper “STM inside a map” concurrency (couldn’t easily google it right now, but it’s there).

I think single atom with serial writes is still better. Firstly, I think it’s more performant still, serial updates on atom are fast. And secondly, it’s much easier to reason about such code, much easier to test and debug it.