views:

382

answers:

6

I'm told that Clojure has lockless concurrency and that this is Important.

I've used a number of languages but didn't realize they were performing locks behind the scenes.

Why is this an advantage in Clojure (or in any language that has this feature)?

+3  A: 

I can't speak about Clojure specifically, but ... it means you don't need to wait for someone to be done with something before you can get to work. Which is great.

Typically it's achieved with immutable types. If nothing can be modified, you don't really need to wait till someone else is done with it before you can access it.

Noon Silk
Who is 'someone'? Could you give an example? I don't think there are any 'someone's sharing my objects with me. Maybe I should check under the bed.
i_like_monkeys
*someone* is just another piece of code, in another thread, accessing that object.
Noon Silk
It's sometimes faster sometimes slower - like most optimizations that are done without measuring. So sometimes it's a good thing, and sometimes those locks would have been better. This is why we're called software **engineers**.
Eloff
+4  A: 

Deadlocks. Or to be more correct the lack of them.

One of the biggest problems in most languages is that you end up with deadlocks that are:

  1. Hell on earth to debug.
  2. Difficult to be sure you have gotten rid.

Now with no locks, obviously you won't run into deadlocks.

tomjen
I've never encountered a deadlock that I was aware of. Is it happening more frequently than I realize perhaps? I guess I'm just not familiar with this issue even though I've programmed a lot. The only locking issues I've been aware of were in the database.
i_like_monkeys
@i_like_monkeysIf you are writing a webfrontend in C# then most of the locking issues are going to be in the lower layers (the webserver and the database), but if you are going to develop programs that is definitely an issue.
tomjen
If you have a deadlock, the symptom will usually be that your program freezes up (0% CPU usage, none of its tasks get done, ever again, until you manually kill it with Task Manager or etc). Deadlocks can occur if your threads are holding more than one lock at a time, and different threads are acquiring the locks in a different order.
Jeremy Friesner
+1  A: 

The benefit of lockless concurrency is the lack of complexity in the program. In imperative languages, concurrent programming relies on locks, and once the program gets even moderately complex, difficult-to-fix deadlock bugs creep in.

Mike Mazur
Has this ever happened to you?
i_like_monkeys
+6  A: 

Lockless concurrency also provides the nice advantage that readers never have to wait for other readers. This is especially useful when many threads will be reading data from a single source. You still need to define the data dependencies in your program and explicitly define the parts of a transaction that can be commuted safely.
STM saves you from deadlocks and almost all occurrences of livelock though it does not save you from concurrency failures you can still create cases where a transaction will fail because it lacks the resources to maintain its history but the important part is that concurrency failures will be explicit and you can recover from them

Arthur Ulfeldt
Yep! STM = Software Transactional Memory. That's a good work to look up if you want to know more about how this works.
Anders Rune Jensen
+1  A: 

As long as you write strictly sequential programs (do A, then B, then C; finished!) you don't have concurrency problems, and a language's concurrency mechanisms remain irrelevant.

When you graduate from "programming exercise" programs to real world stuff, pretty soon you encounter problems whose solution is multi-threading (or whatever flavor of concurrency you have available).

Case: Programs with a GUI. Say you're writing an editor with spell checking. You want the spell checker to be quietly doing its thing in the background, yet you want the GUI to smoothly accept user input. So you run those two activities as separate threads.

Case: I recently wrote a program (for work) that gathers statistics from two log files and writes them to a database. Each file takes about 3 minutes to process. I moved those processes into two threads that run side by side, cutting total processing time from 6 minutes to a little over 3.

Case: Scientific/engineering simulation software. There are lots and lots of problems that are solved by calculating some effect (heat flow, say) at every point in a 3 dimensional grid representing your test subject (star nucleus, nuclear explosion, geographic dispersion of an insect population...). Basically the same computation is done at every point, and at lots of points, so it makes sense to have them done in parallel.

In all those cases and many more, whenever two computing processes access the same memory (= variables, if you like) at roughly the same time there is potential for them interfering with each other and messing up each others' work. The huge branch of Computer Science that deals with "concurrent programming" deals with ideas on how to solve this kind of problem.

A reasonably useful starting discussion of this topic can be found in Wikipedia.

Carl Smotricz
A: 

Such "lockless concurrency" isn't really a feature of a language; rather, it's a feature of a platform or runtime environment, and woe be the language that won't get out of the way to give you access to these facilities.

Thinking about the trades between lock-based and lock-free concurrency is analogous to the metacircular evaluator problem: one can implement locks in terms of atomic operations (e.g. compare-and-swap, or CAS), and one can implement atomic operations in terms of locks. Which should be at the bottom?

seh