We were recently reminded that initialization of lazy vals locks on the object holding the lazy val. This makes using lazy vals in a concurrent setting awkward if calculating a value is an expensive operation and thus the lock may be hold for a long time. It is especially expensive
if each (initializing) access to an easily calculated lazy val in the same object is then obstructed by a long-hold lock for calculating another lazy val. This would lead to a rule to use lazy vals only if
needed for performance reasons for long-running calculations but not for smaller calculations. This, however isn't possible because lazy vals are commonly needed to get around the initialization order
So, lazy vals, while idiomatic, are an obstacle to parallelization. This is a pity because in the common cake pattern you will likely compose several unrelated traits which may contain lazy vals which now can't be initialized in parallel which in turn slows down the initialization of applications built with the cake pattern for their central object. In an application of a certain size debugging these
problem is no fun because the central object will be called from everywhere and to properly parallelize you have to repeatedly start up your program to find all accesses to lazy vals in the call path (or
use a profiler).
One workaround I see right now is to manually touch the cheap lazy-vals to be used concurrently up front to be sure their calculation won't run into a lock. The other one is to use a special
LazyVal class like I used to do in Java and lock on it for the long-running calculations. Both workarounds aren't nearly as usable as the built-in keyword.
This may seem like a special case but IMO this will become more of a trap in the future if more software has to run concurrently. Therefore, lazy vals should be improved to have a lock per lazy val in the default case. A final solution to this problem would have to balance memory use (the per-lazy-val lock has to be saved somewhere) while still maintaining ease of use. David MacIver once conceived of a way to do so.