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

Regan Heath regan at netmail.co.nz
Wed May 30 10:40:18 PDT 2012


On Wed, 30 May 2012 18:16:38 +0100, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:
> On 5/30/12 9:43 AM, Regan Heath wrote:
>> On Wed, 30 May 2012 17:00:43 +0100, Andrei Alexandrescu
>> <SeeWebsiteForEmail at erdani.org> wrote:
>>
>>> On 5/30/12 5:32 AM, Regan Heath wrote:
>>>> On Wed, 30 May 2012 10:21:00 +0100, deadalnix <deadalnix at gmail.com>
>>>> wrote:
>>>>> You don't want to synchronize on ANY object. You want to synchronize
>>>>> on explicit mutexes.
>>>>
>>>> +1 .. this is the key point/issue.
>>>
>>> TDPL's design only allows for entire synchronized classes (not
>>> separate synchronized and unsynchronized methods), which pair mutexes
>>> with the data they protect. This is more restrictive than exposing
>>> mutexes, but in a good way. We use such a library artifact in C++ at
>>> Facebook all the time, to great success.
>>
>> Can you call pass them to a synchronized statement? i.e.
>>
>> TDPLStyleSynchClass a = new TDPLStyleSynchClass();
>> synchronized(a) {
>> }
>
> Yes. Well I recommend acquiring the text! :o)
>
>> ... because, if you can, then you're exposing the mutex.
>
> No.

For the purposes of this thread, and the anti-pattern/problem we're  
discussing, you are.  It is the combination of synchronized  
classes/methods (implicit locking) and external synchronized statements  
(explicit locking) which result in the unexpected, accidental, and hard to  
see deadlocks we're talking about here.

>>> People shouldn't create designs that have synchronized classes
>>> referring to one another naively. Designing with mutexes (explicit or
>>> implicit) will always create the possibility of deadlock, so examples
>>> how that could happen are easy to come across.
>>
>> True. But in my Example 1
>
> Your example 1 should not compile.

o.. k.. I expected you would get my meaning with the simplified example.   
Here you are:

import core.thread;
import std.random;
import std.stdio;

class C
{
   synchronized void ccc() { writefln("c.ccc()"); }
}

class D
{
   synchronized void ddd() { writefln("d.ddd()"); }
}

shared C c;
shared D d;

void main()
{
   c = new shared(C)();
   d = new shared(D)();
   Thread thread1 = new Thread( &threadFunc1 );
   Thread thread2 = new Thread( &threadFunc2 );
   thread1.start();
   thread2.start();
   Thread.sleep(dur!("seconds")(60));
}

void threadFunc1()
{
   Random gen = rndGen();

   while(1)
   {
     synchronized(c)
     {
       printf("threadFunc1 sync(c) %p, obtain d.. %p\n", c, d);
       d.ddd();
     }
	
     Thread.sleep(dur!("usecs")(gen.front()));
     gen.popFront();
   }
}

void threadFunc2()
{
   Random gen = rndGen();

   while(1)
   {
     synchronized(d)
     {
       printf("threadFunc1 sync(d) %p, obtain c.. %p\n", d, c);
       c.ccc();
     }
	
     Thread.sleep(dur!("usecs")(gen.front()));
     gen.popFront();
   }
}

Runs and deadlocks immediately.

>>> TDPL improves on deadlocks by introducing synchronized statements with
>>> more than one argument, see 13.15.
>>
>> Is there anywhere I can see this online? (for free :p)
>
> http://goo.gl/ZhPM2

Thanks.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/


More information about the Digitalmars-d mailing list