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

Regan Heath regan at netmail.co.nz
Thu May 31 08:05:59 PDT 2012


On Thu, 31 May 2012 15:49:52 +0100, Dmitry Olshansky  
<dmitry.olsh at gmail.com> wrote:
> OK let me land you a hand here. My proposal, that I think fits your  
> ideas quite favorably.
>
> I'll enumerate certain assumptions beforehand since it's one of most  
> confusing threads I ever followed.
>
> 1. synchronized class means: always allocate hidden monitor mutex, lock  
> it on every public method of this class.
>
> 2. synchronized(x,y,z) is lowered to (I use Steven's idea):
> 	auto sorted = total_order(x,y,z);//conceptual, sorted is tuple of x,y,z  
> sorted
> 	FOR EACH item IN sorted tuple add code in [[ ... ]]
> 	[[// conceptual
> 		item.__lock();
> 		scope(exit) item.__unlock();
> 	]]
> In other words it works for every object that defines lock/unlock.  
> Multiple object version works only if there is opCmp defined. (by  
> address whatever, any total ordering should work)
>
>
> Per definition above synchronized classes AS IS can't be *synchronized*  
> on. Instead their public methods are implicitly synchronized.
>
> The end result is:
>
> User can synchronize on various synchronization entities and even plug  
> in custom synchronization primitives (say OS Y provides have this fancy  
> lock type Z). It's explicit in as sense that object supports it via  
> __lock__/unlock. Obviously one still can use __lock/__unlock explicitly  
> just don't forget to wear big HERE BE DRAGONS banner.
>
> Synchronized class encapsulate mutex completely - nobody aside from  
> designer of the class may (a)use it.
>
> Does it makes sense?

Yes, and it's all more intentional/flexible than what we have now, but.. :)

Does it address what I thought was the main "problem" case.  That is, as  
soon as you lock 2 objects, one via a synchronized() statement and the  
other via a synchronized method you can get a non-obvious deadlock. e.g.

synchronized class A
{
   void foo() {} // implicitly locks instance of A
}

class B
{
   void __lock() {}   // locks instance of B
   void __unlock() {} // unlocks instance of B
}

shared A a;
shared B b;

void main()
{
   a = new shared(A)();
   b = new shared(B)();
   ..start thread which locks a then b..
   synchronized(b)  // locks b 'explicitly'
   {
     a.foo();       // locks a 'implicitly'
   }
}

.. but, hang on, can a thread actually lock a and then b?  If 'a' cannot  
participate in a synchronized statement (which it can't under this  
proposal) then no, there is no way to lock 'a' except by calling a  
member.  So, provided 'a' does not have a member which locks 'b' - were  
deadlock safe!

So.. problem solved; by preventing external/public lock/unlock on a  
synchronized class.  (I think the proposal should enforce this  
restriction; synchronized classes cannot define __lock/__unlock).

R

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


More information about the Digitalmars-d mailing list