On Thu, 31 May 2012 19:29:27 +0100, Andrei Alexandrescu <[email protected]> wrote:
On 5/31/12 7:01 AM, Regan Heath wrote:
Sorry, I have no spare time to spare. You're getting free ideas/thoughts
from me, feel free to ignore them.

Thanks. Let me know if I understand correctly that your idea boils down to "I don't like synchronized, let's deprecate it and get back to core.sync.mutex and recommend the private thingamaroo." In that case, I disagree. I believe synchronized has good merits that are being ignored.

To present this another way..

Your motivation for the construct: "synchronized(a, b, ...)" was to prevent deadlocks caused by:

[thread1]
synchronized(a)
{
  synchronized(b)
  {
  }
}

[thread2]
synchronized(b)
{
  synchronized(a)
  {
  }
}

right?

Well, this is the same problem expressed several other less-obvious (to code inspection) ways:

1.
[thread1]
synchronized(a)
{
  b.foo();  // where b.foo is { synchronized(this) { ... } }
}

[thread2]
synchronized(b)
{
  a.foo();  // where a.foo is { synchronized(this) { ... } }
}

2.
[thread1]
synchronized(a)
{
  b.foo();  // where b.foo is synchronized void foo() { ... }
}

[thread2]
synchronized(b)
{
  a.foo();  // where a.foo is synchronized void foo() { ... }
}

#1 can be solved (in most/many cases) by doing 2 things, first by disallowing that idiom completely in favour of synchronized classes/class methods (which I think TDPL does?), and second by adding more control as described below in(#2)

#2 can be solved (in most/many cases) by allowing greater control over who can participate in synchronized statements. If either 'a' or 'b' were not allowed to participate in a synchronized statement, then either thread1 or thread2 would be invalid code and a deadlock involving these 2 objects would be impossible(*).

There will still exist some synchronized classes which want to participate in synchronized statements but I'm thinking/hoping this is rare and if the default for D is 'not allowed' then it becomes a conscious choice and we can supply the developer with a warning in the docs which describe how to do it, introduce the synchronized(a, b, ...) construct, etc.

From another angle.. I'm guessing it's either impossible or very hard to detect the 2 cases presented above at compile time? Essentially the compiler would need to know which code could execute in separate threads, then determine lock ordering for all shared/lockable objects, then detect cases of both (lock a, b) and (lock b, a) in separate threads. Sounds tricky.

R

(*)using synchronized statements - one could still keep a reference to the other internally and call a synchronized member function from within a synchronized member function

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

Reply via email to