synchronized (this[.classinfo]) in druntime and phobos
Regan Heath
regan at netmail.co.nz
Wed May 30 06:10:11 PDT 2012
On Wed, 30 May 2012 13:43:14 +0100, deadalnix <deadalnix at gmail.com> wrote:
> Le 30/05/2012 14:32, Regan Heath a écrit :
>> 1. Prevent locking on any/every object. People would have to create a
>> separate mutex object for locking. This is a little tedious, but it does
>> make people think about the scope of the locking (where to put the
>> mutex, who can see/use it, etc). On the flipside it can make people
>> re-use a mutex for multiple conceptual critical section areas of code,
>> which is less than ideal, but at least it's not 'broken'.
>>
>
> It is suboptimal, but correct.
Indeed, and can be made optimal with some fine-tuning/work.
>> 2. Allow locking on any/every object but use a different mutex for
>> synchronized class/methods. So 'synchronized' on a method call locks a
>> private mutex object, not the object itself. And synchronized(object)
>> locks the public mutex object. The downside here is that now every
>> object potentially has 2 mutex objects/handles internally - a public and
>> a private one.
>>
>
> It doesn't address most of the drawback cited. Notably the fact that
> every object have a monitor field, but most of them will not use it.
True, I was just mentioning it as an option that solves the key
issue/problem - not as the best solution to that problem. I think #1 is
better.
Ultimately the "problem" that needs solving is the fact that synchronized
classes/methods use a public mutex and this exposure makes deadlocks more
likely. I was hoping that by giving some examples in code, it would
become clearer to the people who don't see what all the fuss is about.
Yes, having to manually create a mutex is a pain, and as Andrei has
mentioned a few times having 2 separate things (one object to lock, one
mutex) which conceptually should be one thing is worse from an
understanding/maintenance point of view, however..
1. If the mutex is intended to lock a single object then we can make the
following options available:
a. A Lockable class to derive from.
b. A Lockable struct to compose with (assuming here that the struct will
be created/destroyed with the object).
c. A Lockable!(T) wrapper template/struct/class to wrap objects to be
locked.
d. A Lockable interface which classes may implement.
e. Some sort of compiler magic where it supplies the mutex for
objects/methods marked with "synchronized" or involved in a
synchronized(object) statement.
2. If the scope of the locking is greater than a single object, then a
separate mutex is required/desired anyway.
1a. would contain a mutex primitive and lock/tryLock/unlock methods (it
would implement the interface in 1d)
1b. would also contain a mutex primitive and alias could be used to expose
the lock/tryLock/unlock methods (it would implement the interface in 1d)
1c. is actually a technique I have used a lot in C++ where the template
class is created on the stack of a function/critical section and it
(optionally) locks on creation (or later when lock() is called) and always
unlocks on destruction as it leaves scope (by any means). It's a very
robust pattern, and is similar (the inspiration/or result) of/to the
synchronized block itself.
1d. could be a requirement for classes which are to be used in
synchronized statements i.e.
class A : Lockable
{
void lock() {}
void unlock() {}
}
A a = new A();
synchronized(a)
{ // calls a.lock()
...
} // calls a.unlock()
1e. I leave as a opener to Walter/Andrei/the reader .. I've seen many a
genius idea pop out of nowhere on this forum.
IMO, the wasted space used by the monitor isn't ideal, but it's not a
"problem" for the general case. It is a problem for people with limited
memory environments but that's another topic. Talking about both is only
clouding the discussional waters so to speak.
R
--
Using Opera's revolutionary email client: http://www.opera.com/mail/
More information about the Digitalmars-d
mailing list