synchronized (this[.classinfo]) in druntime and phobos

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Thu May 31 04:13:00 PDT 2012


On 5/31/12 3:27 AM, Regan Heath wrote:
> I think
> the mutex is "available for locking and unlocking" <- need a word for
> that, which is not "exposed". How about accessible, available, usable,
> or just plain lockable .. So, the problem here is that the mutex is
> lockable by external code via synchronized() and this means a certain
> type of deadlock is possible.

But this is a protection/visibility issue, which is orthogonal on the 
locking capability. It's as if you say "int is not good because anyone 
can overflow it." Okay! Make it private inside a CheckedInt class.

> Moving on..
>
> I think the change mentioned in TDPL to restrict synchronized to
> synchronized classes is a step in the right direction WRT wasted monitor
> space and people freely locking anything. But, it is exactly the case
> which results in more possible deadlocks (the cause of this thread) AND
> I think it's actually far more likely people will want to use a
> synchronized statement on a class which is not itself synchronized, like
> for example an existing container class.
>
> Given that, restricting synchronized statements to synchronized classes
> seems entirely wrong to me.

So where's the mutex that would be used to synchronize objects that are 
not synchronizable?

> In fact, I would say you almost want to stop
> people using synchronized statements on synchronized classes because:
> 1. If a synchronized class is written correctly it should not be
> necessary in the general case(*)
> 2. It raises the chances of deadlocks (the cause of this thread).
> 3. It means that classes in general will be simpler to write (no need to
> worry about synchronization) and also more lightweight for use in
> non-threaded/non-shared cases. (because we'd provide a template wrapper
> to make them synchronizable)

There are cases in which you want to do multiple operations under a 
single critical section, even though the API is otherwise well-designed. 
That may be for correctness, efficiency, or both. I don't see why we'd 
want to disallow that, it's a good idiom.

> So, more and more I'm thinking it would be better to provide a
> library/runtime co-operative solution where we have an interface which
> is required for synchronized statements, and a wrapper template to
> implement that interface for any existing non-synchronized class.
> Meaning, the choice is either to write a synchronized class (rare) or a
> non-synchronized class - knowing it can easily be synchronized if/when
> needed.

Looking forward for a fleshed out proposal. Make sure you motivate it 
properly.

> The "liquid lock" problem mentioned earlier is an interesting one that I
> have not personally experienced, perhaps because I don't lock anything
> but mutex primitives and I never to re-assign these.
>
> (*) Locking on a larger scope can be achieved by providing a method
> taking a delegate (see earlier thread/replies) and/or exposing
> lock/unlock for those few situations where the delegate method cannot be
> used. These are the few cases in which this cannot be avoided as the
> lock/unlock are separated by more than a single scope (so synchronized
> statements don't help in these cases either).

On first look, the inversion of control using delegates delegates has 
similar liabilities as straight scoped locking.


Andrei



More information about the Digitalmars-d mailing list