Skip to content

Comment on Concurrent Programming, with Examplesparent

Comments

I'm just an idiot EE who learned to program, but it seems like functional languages without side-effects accomplish their task by basically working on data structures stored on the stack. That basically means each call stack has its own data structure. If you wrote threaded code so that each thread had its own data structure, and worked off a shared set of read-only data structures, you wouldn't need to worry about locking.

IME locking isn't really all that hard until you need to squeeze out performance. If you can handle one big dumb lock around everything, it's easy. The finer grained your locking gets, the harder it is to get right(even then, lock hierarchies can help to a great degree).

One big dumb lock only protects against data races. There are other classes of concurrency bugs that require smart locking to avoid, and it's always a pain.

For example, iterator invalidation. Which is probably the most common thing I've seen when people use dumb locks to make a concurrent program sound. Either your iterators need to be aware of the lock and hold it through their lifetime (which means practically only one iterator can exist, which is undesirable) or your datastructure needs to be aware of outstanding iterators to it and update them (which means you have added logic to simple mutations, which is also undesirable).

It's problems like that you look for in non-functional languages that require library authors to say things like "this is/isn't thread safe" in their documentation, while providing those guarantees manually. And as a consumer of the library you need to be aware of these things and look for them, and what an error looks like when someone messes up.

I don't know what you're trying to say about stacks/the call stack in functional languages, because they implement their patterns in variety of ways - including locking. It's just about providing particular guarantees in the API, and the benefits of those guarantees are that it prevents entire classes of bugs like iterator invalidation and data races.

There are also all sorts of clever data structures you can use that don't require duplication of the underlying data. The easiest is a singly linked list without insertion. No locks required.

The problem is that if you have one big dumb lock around everything then you have no actual concurrency or parallelism.

Depends on what the big dumb lock protects. You may still be able to process data you accessed while holding the big dumb lock.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.