On Mon, 28 May 2012 18:36:13 -0400, Alex Rønne Petersen <[email protected]> wrote:

Hi,

I've seen several occurrences of synchronized (this) and synchronized (this.classinfo) in both druntime and phobos by now. I propose that we officially ban these patterns with extreme prejudice.

1) Locking on the object instance is a HORRIBLE IDEA. Anyone who happens to use the object for locking will most likely end up with a deadlock on their hands. 2) Locking on something as fundamental as type info means that any arbitrary part of the application could cause a deadlock by doing the same.

Reading all of this thread, I think I agree with you.

Now, I'll point out a couple things:

1. Most code that is written with synchronized is *not* abused.
2. using synchronized(x) should not go away.

Here is what I'm thinking:

First, we give control of the mutex to the author of the type. So instead of an implicit location, and implicit lazy construction, we make everything explicit:

Currently:

synchronized(x)
{
}

translates to

if(x.mutex == null)
   x.mutex = createmutex();
lock(x.mutex)
try
{
}
finally
{
   unlock(x.mutex);
}

So I propose it does this instead (entirely via lowering):

synchronized(x)
{
}

translates to:

auto l = x.__getMutex();
l.lock();
try
{
}
finally
{
   l.unlock();
}

So we have a few benefits here:

1. if typeof(x) does not define __getMutex, the above is a compiler error.
2. We can control the visibility of the mutex, because we can attribute private or protected to the __getMutex function. 3. We can control what kinds of objects of typeof(x) use mutexes. e.g. define __getMutex() shared only. 4. We have control over the type of the lock, it can be anything and does not need to fit into some runtime function's interface.

Second, I propose a somewhat gradual transition. I think on first release, we *still* keep the allocated word in the class instance, and keep the druntime function which lazily allocates the mutex. Therefore, changing an object that currently *properly* can use synchronized(this) can be made to work:

class Synchronizable
{
   xxx __getMutex() shared { return _d_getObjectMonitor(this);}
}

We can deprecate that functionality, and the allocated space for the mutex later if desired.

-Steve

Reply via email to