On Wed, Apr 27, 2022 at 2:47 PM Elijah Stone <[email protected]> wrote:
> 1. should the lock be recursive or no?

After sleeping on this...

I've been working with this issue from a variety of perspectives for
most of my programming career. I won't bore you with those details.

But ... I would summarize three major perspectives for dealing with locking:

Below the level of abstraction for the locks (e.g. hardware), locking
does not exist as an abstraction. Everything happens in parallel and
locking is out of the picture. (In hardware, at a low level you
synchronize based on your inputs, and maybe use a clock to keep things
in sync, if the design has gotten out of control / has become too
complex to understand.)

At the level of abstraction of the locks, you need a careful,
disciplined approach or you don't understand what's going on. Locking
here is about providing consistent access to resources, and you need
to enumerate those and you need to be concerned about time. You get
deadlocks when different parts of your code lock multiple elements
from the same set of resources in a different order from in other
parts of your code.

Above the level of abstraction of the locks, they're something of a
mystery -- things work, or they don't, and you develop habits based on
that, and use superstition if necessary to cope with the consequences.
(The internet is maybe a good example here.)

In communicating systems, you deal with issues of atomicity by either
designing your system to work with stale data (e.g. analytics) or by
designing your system to be cheap and throwaway (e.g. editing systems,
or erlang). When things go wrong in a feedback loop you start over (or
give up (or give up and start over)). And, in the end, there's always
going to be someone who doesn't like it, and there's a certain amount
of back and forth as a consequence.

Anyways... this choice -- between re-entrant and non-reentrant locking
-- winds up being useful or not based on your system architecture.
Given a mechanism to achieve atomicity, ... once you have one kind of
lock you can build the other kind on top of it.

And, at the end of the day, you're going to need both.

So... after sleeping on this... my gut feeling is that non-reentrant
locking is best thought of as a "relatively global" "extremely short
term" low level mechanism which gets used when constructing longer
term reentrant locks.

And, when reading the literature on these kinds of topics, I think
it's important to understand the author's perspective -- the level of
abstraction they were working at, the kinds of things that they were
building, and the nature (and timing) of the feedback loops they were
working with, and ideally some of the details of the problems they
were tackling,

But when talking about the J implementation and J's internal resources
(J's "variables" or "names), it makes sense to me to use non-reentrant
locks inside the implementation to provide reentrant locking which
locks and unlocks J's internal resources at the same level of
abstraction as J's stack (which is J's primary "reentrant code
mechanism").


--
Raul
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to