Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Clojure is memory safe and no data races possible?


Memory safe, perhaps, but data races are definitely possible. The main issue is that their STM system doesn't scale very well. It is good enough if you want to keep a simple CRUD GUI in sync but don't expect to be building high performance web servers anytime soon with Clojure atomics. You can't just create and throw those around willy-nilly like Goroutines. Clojure people doesn't like talking about the language's weaknesses but I have seen quite a few Clojure projects get rewritten because of maintenance cost and runtime inefficiencies. Project Loom is the best option right now for scalable Clojure concurrency/parallelism.


STM, atomics and channels are all different things that can be use to build different kinds of systems, so I think it's good to disambiguate them when talking about concurrency problems and their tradeoffs.

Clojure' STM is basically unused. It's a suite of functions and a container type `ref` that allows you to do transactions in memory and keep everything consistent within the view of a transaction. The overhead required to do the book keeping for these transactions is often not worth it for most use cases in practice.

Clojure also, as an alternative, gives you `atom` which is a type that implements a simple thread safe compare-and-swap. This ends up being sufficient for many cases of sharing state between threads. When combined with Clojure's immutable data structures, one can often use them as a simple in memory database.

Those two things are about sharing memory, but has nothing to do with what the article talks about: green threads.

clojure.core.async, as the article succinctly explains, allows you to create "goroutines" or green threads which are then multiplexed across some number of OS threads. This can allow you to create many more threads for computation than you have OS threads, and combined with thread locals and atoms can allow one to build large scale systems.

Clojure's STM and atomics are sort of a non-sequitur from what the article is talking about

Now as for downsides of Clojure, there are plenty of gotchas in practice that can lead people to issues with the three things above:

* STM is slow and rarely useful compared to regular atomics

* atoms CAS assumes you are using immutable data structures

* core.async has a lot of sharp edges, including lack of first-class error handling and the fact that doing synchronous I/O on a go routine can end up starving the thread pool they are running on

I've never built a high performance web server, but I imagine it's possible with Clojure; it would probably require you to probably eschew immutable data structures within the plumbing (for performance) and use an async I/O framework along with core.async to get competitive with a language like go. For shared memory, you probably would end up eschewing compare-and-swap for something more bare bones like locks, which you have access to via Java interop. At that point, you may wonder why you even chose Clojure in the first place instead of using Java directly. :D

Project Loom really only helps solve the problem that core.async is trying to solve, and applications would still make use of atomics like `atom` and basic Java atomic values. My hope is that it makes it easier to do I/O, since it sounds like along with loom fibers the project is adding first class support for suspending and resuming on fundamental I/O operations. Time will tell.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: