Synchronized classes have no public members
Jonathan M Davis via Digitalmars-d
digitalmars-d at puremagic.com
Thu Oct 15 08:50:34 PDT 2015
On Thursday, 15 October 2015 at 15:16:59 UTC, Steven
Schveighoffer wrote:
> I don't really understand all the disdain for synchronized
> here...
Because it's usually either the wrong solution or just
unnecessary. If you are going to have a single mutex for an
entire object, then it's nice in the way that it's nice that
invariants are nice. They're not at all necessary, because the
same thing can be done manually via assertions inside of all of
the public member functions, but it does make them less
error-prone.
However, it's frequently the case that having a mutex per class
object is the wrong way to go. Usually, it's better to have
tighter locks than that which target specific member variables
rather than the class as a whole, and when you do want it at the
class level, it's frequently better to have the user of the class
do the locking, since in that case, there's a decent chance that
the object is a member variable inside of another class/struct
where it and another set of variables need to share a mutex, so
having a mutex built into the object is redundant and causes
unnecessary overhead. Having the mutex at the class level is
simply too inflexible and arguably encourages bad coding
practices. So, having synchronized on classes or functions is of
questionable value and arguably harmful - though the fact that
having it on classes would allow us to strip away the outer layer
of shared on the class' members does add some value.
Ultimately, the only advantages to synchronized classes IMHO are:
1. They makes porting Java code easier.
2. Similar to how invariant helps with assertions at the class
level, they make it easier to use a mutex at the class level
correctly (though IMHO, that's almost always the wrong design).
3. They give us a way to implicitly cast away shared on some
level (though not necessarily enough to be worth it).
So, they add _some_ value, but I'm not at all convinced that
they're worth it.
As for synchronized statements/blocks, they're simply syntactic
sugar that add no real value that I can see, and they can do less
then the equivalent with guards/autolocks. These two pieces of
code are equivalent:
synchronized(mutex)
{
}
{
Guard guard(mutex);
}
and the second one is far more flexible, since it allows for
stuff like guard.unlock() or using the mutex with a condition
variable. So, synchronized statements are a poor-man's
guard/autolock and simply not worth having IMHO unless we find
some way that it allows us to get the compiler to do stuff (like
being able to implicitly remove shared on some level, though
because you have arbitrary code within the synchronized block and
aren't dealing with encapsulated shared variables like with
synchronized classes, I don't see how we really can get the
compiler to do much special with synchronized blocks).
I don't know that it's worth it to remove synchronized from the
language, but certainly, if we were starting from scratch, I'd be
arguing against it. I think that it's a Java-ism that shouldn't
have been ported to D. Java and C# had no choice, because they
don't have proper RAII or scope statements, but we don't have
that problem.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list