Synchronized Class Constructors (Was: Re: Some Issues With Synchronized)

Andrew Wiley wiley.andrew.j at gmail.com
Thu Dec 22 17:35:10 PST 2011


Alright, looks like my code examples were too long (see Some Issues
With Synchronized), but I've found an issue with synchronized that I
think might be a bug (or a design bug).
In simple terms, constructors for synchronized classes are
synchronized. This should rarely cause problems, but it's unnecessary
and breaks code like this:
---
synchronized class Bob {
    this() {
        auto lock = new Mutex(this); // put an explicitly allocated
lock as the monitor for this object
    }
}
---

The problem is that since the constructor is synchronized, the runtime
tries to lock the monitor (and lazily initializes it), but that lock
is then replaced by the explicitly allocated Mutex. When the runtime
tries to unlock the monitor at the end of the constructor, an
assertion is hit because the thread doesn't hold the newly allocated
Mutex.

This version works:
---
synchronized class Bob {
    this() {
        auto lock = new Mutex(this); // put an explicitly allocated
lock as the monitor for this object
        lock.lock();
    }
}
---

The issue is that while this use case is rare, synchronizing a
constructor by default, even with synchronized classes, makes very
little sense. It *might* be necessary if a poorly written constructor
leaks references to an object before it is fully initialized, but in
that case, I believe the user should be responsible for ensuring
proper synchronization. In general, leaking references to an object in
a constructor is a bad idea, no matter the context, and should be
examined very closely to ensure proper ordering.

I do now know of another language that synchronizes constructors (Java
explicitly disallows it).

The D spec on dlang.org does not contain any information about what
happens when the synchronized modifier is applied to an entire class,
and TDPL says this:
---
The synchronized class-level attribute affects objects of type shared
(BankAccount) and automatically serializes calls to any method of the
class. Also, protection checks get stricter for synchronized classes.
Recall that according to § 11.1 on page 337, normal protection checks
ordinarily do allow access to non-public members for all code within a
module. Not so for synchronized classes, which obey the following
rules:
- No public data is allowed at all.
- Access to protected members is restricted to methods of the class
and its descendants.
- Access to private members is restricted to methods of the class.
---

So is this a bug or a feature?


More information about the Digitalmars-d mailing list