
Ask HN: Grokking concurrent applications? - tastyface
As someone who&#x27;s been programming professionally for several years, I&#x27;m embarrassed to admit that I barely have any experience with concurrent programming. My next project heavily relies on database and network sync, so I figured it would be a good opportunity to brush up on the basics. I&#x27;m currently trying to internalize the inner workings of a popular open-source database project (YapDatabase), but I&#x27;ve run into a significant mental block: whenever I try to visualize the flow of a concurrent program in time, I just can&#x27;t seem to keep it in my head. With single-threaded programming, things are a lot easier. Control flow is predictable and circuit-like, allowing you to draw the structure of most programs out on paper. But it seems that with concurrency, you&#x27;re essentially adding a third dimension to the mix: not something that can easily be represented in 2D space! Whenever I have to reason about overlapping thread interactions, obscure deadlock conditions, and synchronization summersaults, I just feel like I immediately get lost and have to start over. There&#x27;s no stable structure for me to grab onto: every overlap of the threads in time has to be considered!<p>I know this is possibly too general of a question, but is there a systematic approach to reasoning about concurrent programs?<p>(In the meantime, I suppose I&#x27;m going to keep reading the code over and over and hope that things start to stick.)
======
davismwfl
This is a huge topic and you are right it probably isn't an easy thing to try
and answer here, but maybe some hints to help you.

You are correct to almost view multi-threaded applications (or distributed
processes really) as essentially a 3d problem. In a single threaded program
time is not ever really a factor, sure you want performance so you worry about
how long something might take to execute, but that is relevant to the singular
flow. In concurrent applications time is a dimension that is essentially
uncontrolled and you have to instead rely on state and some form of message
handling/passing. Regardless of how it gets implemented, concurrent
applications (threads or distributed processes/apps) all have to communicate.
Sometimes that is through shared memory, or through shared variables (with
associated locks/mutex etc), but in the end they all have to talk -- I've seen
files used to communicate etc.

So as for where to start when trying to understand an existing concurrent
application. Pick one component and find out who it talks to or depends on,
figure out how it talks to everyone, and then start your map from there.
Instead of mapping function calls you are mapping communication flow and
paths. Then within those communication paths each component will have a
functional map generally that you can follow like a more traditional
application.

Some may disagree but to me this is the easiest way to view concurrent or
distributed applications. Honestly, once you figure it out, you'll either love
or hate it. I personally love it, but it isn't for every problem.

------
sfrailsdev
I think it's helpful to focus on when things write to a shared resource or
utilize something that may have been changed elsewhere. Any subsequent read of
that resource may change. In face, in a poorly designed system you could read
a value as it's being changed, for example, a function walking a string as the
string's memory is released.

