1

There's a common belief and multiple sources (including wiki) that claim this idiom to be an anti-pattern.

  1. What are the arguments against using it in production code given the correct implementation is used (for example, using volatile)

  2. What are the appropriate alternatives for implementing lazy initialization in a multithreaded environment ? Locking the whole method may become a bottleneck and even while modern synchronization is relatively cheap, it's still much slower especially under contention. Static holder seems to be a language-specific and a bit ugly hack (at least for me). Atomics-based implementation seems not be so different from traditional DCL while allowing multiple calculations or requires more complicated code. For example, Scala is still using DCL for implementing the lazy values while proposed alternative seems to be much more complicated.

Community
  • 1
  • 1
AngryJuice
  • 61
  • 1
  • 6
  • 4
    "Static holder seems to be a language-specific" - correctly implementing double-checked locking is *also* language-specific, *and* harder to get right. Fundamentally, when you're doing something which relies on the low-level memory model of the language, it's hard to be both non-language-specific *and* efficient. ("Guaranteed to work for all languages" implementations are pretty much bound to be overkill.) – Jon Skeet Aug 12 '14 at 10:48
  • 1
    See also [*Initialization-on-demand holder idiom*](http://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom). – trashgod Aug 12 '14 at 10:54
  • @JonSkeet I kind of agree with you here, but while DCL is a common idiom for lazy initialization (which just needs to be adjusted in Java), the static holder is a much more Java-specific thing. It also requires introducing additional abstraction (a new class) only for technical reasons. – AngryJuice Aug 12 '14 at 11:02
  • Calling the static holder pattern “a bit ugly hack” while comparing with *double checked locking* seems a bit … uhm … weird? Btw. the static holder does not need the introduction of another class. Using the same class which actually manages the resource is sufficient in most of the cases. In Java *all* classes are initialized lazily, not only the ones using the static holder pattern intentionally. Often the thought that the initialization has to be deferred even more is the error in the first place. – Holger Aug 13 '14 at 10:52
  • @Holger I would call it subjective. As for me and for many others (otherwise there won't be so many talks around it), the DCL is pretty natural and works exactly how it looks like except the fact that there are certain technical details you have to understand to make it work properly, which is still required when you write a concurrent code. The holder has the required properties (except the issues with multiple classloaders), but it "piggy-back" on certain language specifics instead, so that's more like a hack or trick if you prefer, like using enums as singletons. – AngryJuice Aug 13 '14 at 13:33
  • @Holger As for not using inner classes, it would initialize all the lazy values in that case once you requested some and while that's indeed usually not a big deal, it does not make such solution an exact alternative to DCL. In general, my concern and the actual question was about why people disapprove this pattern so much and if they have some rational arguments (not just statements) about why it is considered so bad. – AngryJuice Aug 13 '14 at 13:34
  • That’s *really* subjective as, of course, DCL is piggy-backing on a language specific feature as well, in case of Java, it’s piggy-backing on the semantics of the `volatile` variable which is required to make it work. First of all, answering the question why it is so disapproved, it’s not solving any problem. If accessing the lazily created resource is so critical that a tiny `synchronized` operation (a single `null`-check) is a bottleneck, what does DCL, which still requires accessing a `volatile` variable, solve then, especially when comparing to the `final` variable access of Static Holder? – Holger Aug 13 '14 at 13:43
  • I would not call it piggy-back in case of DCL as it uses volatile according to its primary semantics, rather then getting some result as an additional effect like with holder. As for bottleneck, the problem is mostly in blocking, and the difference here may be huge especially under contention. – AngryJuice Aug 13 '14 at 14:05
  • Other thing with is that in practice the actual lazy value initialization is often not so trivial as creating a singleton and usually depends on the non-static object state. – AngryJuice Aug 13 '14 at 14:12

1 Answers1

-2

Don't use double checked locking. Ever. It does not work. Don't try to find a hack to make it work, because it may not on a later JRE.

As far as I know, there is no other save way for lazy initialization than locking the whole object / synchronizing.

synchronized (lock) {
  // lookup

  // lazy init
}

For singletons the static holder (as @trashgod mentioned) is nice, but will not remain single if you have multiple classloaders.

If you require a lazy singleton in a multi-classloader environment, use the ServiceLoader.

Stephan
  • 4,395
  • 3
  • 26
  • 49
  • 3
    Not entirely true, with the Java Memory Model changes of Java 5, double checked locking now should work as long as the initialized field is `volatile`. – Mark Rotteveel Aug 12 '14 at 11:08
  • 3
    The proper implementation is guaranteed to work by the Java Memory Model, same as static holder is guaranteed to work within a single class loader by the spec. – AngryJuice Aug 12 '14 at 11:08
  • 1
    The static holder pattern will *always work*. If you use an unusual class loader setup to load the same class file with different class loaders producing different runtime classes you won’t have a singleton, but that’s not the question; within each of these runtime classes produced this way, the static holder will work. Double checked locking has the same limitations, it will not magically turn multiple runtime classes into one. – Holger Aug 13 '14 at 10:46
  • @Holger Thats not unusual. Try to develop OSGI or Netbeans Bundles. – Stephan Aug 15 '14 at 09:43
  • @Stephan: not worth discussing. Still, there’s no semantic difference between DCL and Static Holder in these scenarios. – Holger Aug 15 '14 at 09:59