digitalmars.D - Synchronized Class Constructors (Was: Re: Some Issues With
- Andrew Wiley (57/57) Dec 22 2011 Alright, looks like my code examples were too long (see Some Issues
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 =3D 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 =3D 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 =A7 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?
Dec 22 2011