The objective of “locking a data-structure in Perl” is certainly not a simple one,

On the contrary, the objective locking shared variables is very simple.

It is to prevent one thread from accessing the locked entity whilst the lock is held by another thread.

given that the entire data management system is centered around the notion of “references.”

Scalars, arrays and hashes are not references.

There is no hierarchy ... anything can refer to anything,

I cannot make any sense of the first part of that statement, because it is immediately contradicted by the second part.

Arrays and hashes contain scalars; and scalars can hold references; and those references can be to other arrays or hashes, hence they can be used to construct hierarchies. Just as in C, arrays of integers can be used to construct hierarchies if some of those integers happen to be pointers to other entities.

I started to point out that no language has hierarchies by default; but then I couldn't justify that because your statement simply makes no sense.

Your lack of understanding -- not just of threading, but Perl, and even programming, in general -- makes it all more frustrating and annoying that you once again have started to dole out "advice" on subjects you simply know nothing useful about.

Now to try and answer the only question that makes any sense:

what the “granularity” of the lock semantics in Perl actually are.

When an entity is locked by one thread; and another thread attempts to take a lock on that same entity; it is blocked -- ie., the lock does not return -- until the first thread unlocks that entity by exiting the scope in which the lock was taken. And that is it.

Now to clarify a few common misunderstandings.

It is perfectly possible to modify a shared entity, locked by one thread, from another thread, whilst it is locked.

It is the act of taking the lock that prevents that thread from doing anything else (to that entity or anything else).

Stated differently, the lock taken by the first thread does not prevent a second thread from doing anything; only the attempt by the second thread to obtain a lock on an already locked entity.

The elements of a shared aggregate -- a hash or array -- are not themselves shared.

They are bog standard scalars.

If however, you store a reference to another shared hash in a hash, you can then lock that other shared hash by applying lock to it via that reference -- by dereferencing it first.

It is also perfectly valid to store a reference to a shared entity within a non-shared aggregate.

The semantics of doing so are a little confusing, but it has its uses.

perhaps this will clarify things: Taking a lock on a shared entity effectively just sets a flag within its internals. And whilst that flag is set, any further attempt to take a lock on that entity blocks until the lock is cleared when the thread that took the lock exits the scope in which it was taken.

But the lock is advisory. If you attempt to modify a locked entity without attempting to take a lock on it first, the modification will succeed. Eben if that means that the code running in the thread that took the lock is rendered incorrect.

The internals of the shared entity will be fine -- an internal, non-user lock will prevent damage to the internals of the entity -- but those internal locks know nothing of the semantics of the user code and it may therefore be rendered incorrect. But it will not crash.

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.

"Science is about questioning the status quo. Questioning authority".

In the absence of evidence, opinion is indistinguishable from prejudice.

Comment on
Re^3: PERL issues a "lock can only be used on shared values" when locking a shared hash