1.4之前不支持,1.5开始支持使用Volatile标记的变量。
Effective Java:
引用
Item 71: Use lazy initialization judiciously
Lazy initialization is the act of delaying the initialization of a field until its
value is needed. If the value is never needed, the field is never initialized. This
technique is applicable to both static and instance fields. While lazy initialization
is primarily an optimization, it can also be used to break harmful circularities in
class and instance initialization [Bloch05, Puzzle 51].
As is the case for most optimizations, the best advice for lazy initialization is
“don’t do it unless you need to” (Item 55). Lazy initialization is a double-edged
sword. It decreases the cost of initializing a class or creating an instance, at the
expense of increasing the cost of accessing the lazily initialized field. Depending
on what fraction of lazily initialized fields eventually require initialization, how
expensive it is to initialize them, and how often each field is accessed, lazy initial-ization can (like many “optimizations”) actually harm performance.
That said, lazy initialization has its uses. If a field is accessed only on a frac-tion of the instances of a class and it is costly to initialize the field, then lazy ini-tialization may be worthwhile. The only way to know for sure is to measure the
performance of the class with and without lazy initialization.
In the presence of multiple threads, lazy initialization is tricky. If two or more
threads share a lazily initialized field, it is critical that some form of synchroniza-tion be employed, or severe bugs can result (Item 66). All of the initialization
techniques discussed in this item are thread-safe.
Under most circumstances, normal initialization is preferable to lazy ini-tialization. Here is a typical declaration for a normally initialized instance field.
Note the use of the final modifier (Item 15):
// Normal initialization of an instance field
private final FieldType field = computeFieldValue();
If you use lazy initialization to break an initialization circularity, use a
synchronized accessor, as it is the simplest, clearest alternative:
// Lazy initialization of instance field - synchronized accessor
private FieldType field;
synchronized FieldType getField() {
if (field == null)
field = computeFieldValue();
return field;
}
ITEM 71: USE LAZY IN ITIALIZATION JUDICIOUSLY 283
Both of these idioms (normal initialization and lazy initialization with a syn-chronized accessor ) are unchanged when applied to static fields, except that you
add the static modifier to the field and accessor declarations.
If you need to use lazy initialization for performance on a static field, use
the lazy initialization holder class idiom . This idiom (also known as the initialize-on-demand holder class idiom) exploits the guarantee that a class will not be ini-tialized until it is used [JLS, 12.4.1]. Here’s how it looks:
// Lazy initialization holder class idiom for static fields
private static class FieldHolder {
static final FieldType field = computeFieldValue();
}
static FieldType getField() { return FieldHolder.field; }
When the getField method is invoked for the first time, it reads Field-Holder.field for the first time, causing the FieldHolder class to get initialized.
The beauty of this idiom is that the getField method is not synchronized and per-forms only a field access, so lazy initialization adds practically nothing to the cost
of access. A modern VM will synchronize field access only to initialize the class.
Once the class is initialized, the VM will patch the code so that subsequent access
to the field does not involve any testing or synchronization.
If you need to use lazy initialization for performance on an instance field,
use the double-check idiom. This idiom avoids the cost of locking when access-ing the field after it has been initialized (Item 67). The idea behind the idiom is to
check the value of the field twice (hence the name double-check): once without
locking, and then, if the field appears to be uninitialized, a second time with lock-ing. Only if the second check indicates that the field is uninitialized does the call
initialize the field. Because there is no locking if the field is already initialized, it
is critical that the field be declared volatile (Item 66). Here is the idiom:
// Double-check idiom for lazy initialization of instance fields
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) { // First check (no locking)
synchronized(this) {
result = field;
if (result == null) // Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
CHAPTER 10 CONCURRENCY 284
This code may appear a bit convoluted. In particular, the need for the local
variable result may be unclear. What this variable does is to ensure that field is
read only once in the common case where it’s already initialized. While not
strictly necessary, this may improve performance and is more elegant by the stan-dards applied to low-level concurrent programming. On my machine, the method
above is about 25 percent faster than the obvious version without a local variable.
Prior to release 1.5, the double-check idiom did not work reliably because the
semantics of the volatile modifier were not stron g enough to support it
[Pugh01]. The memory model introduced in release 1.5 fixed this problem [JLS,
17, Goetz06 16]. Today, the double-check idiom is the technique of choice for
lazily initializing an instance field. While you can apply the double-check idiom
to static fields as well, there is no reason to do so: the lazy initialization holder
class idiom is a better choice.
Two variants of the double-check idiom bear noting. Occasionally, you may
need to lazily initialize an instance field that can tolerate repeated initialization. If
you find yourself in this situation, you can use a variant of the double-check idiom
that dispenses with the second check. It is, not surprisingly, known as the single-check idiom . Here is how it looks. Note that field is still declared volatile :
// Single-check idiom - can cause repeated initialization!
private volatile FieldType field;
private FieldType getField() {
FieldType result = field;
if (result == null)
field = result = computeFieldValue();
return result;
}
All of the initialization techniques discussed in this item apply to primitive
fields as well as object reference fields. Wh en the double- check or single-check
idiom is applied to a numerical primitive field, the field’s value is checked against
0 (the default value for numerical primitive variables) rather than null.
If you don’t care whether every thread recalculates the value of a field, and the
type of the field is a primitive other than long or double , then you may choose to
remove the volatile modifier from the field declaration in the single-check
idiom. This variant is known as the racy single-check idiom. It speeds up field
access on some architectures, at the expense of additional initializations (up to one
per thread that accesses the field). This is definitely an exotic technique, not for
everyday use. It is, however, used by String instances to cache their hash codes.
ITEM 71: USE LAZY IN ITIALIZATION JUDICIOUSLY 285
In summary, you should initialize most fields normally, not lazily. If you must
initialize a field lazily in order to achieve your performance goals, or to break a
harmful initialization circularity, then use the appropriate lazy initialization tech-nique. For instance fields, it is the double-check idiom; for static fields, the lazy
initialization holder class idiom. For instance fields that can tolerate repeated ini-tialization, you may also consider the single-check idiom.
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
分享到:
相关推荐
"idiom翻译软件"是一款专为用户提供了高效翻译服务的应用程序。它被设计用来帮助用户理解和传达不同语言之间的意义,确保跨文化交流的准确性和流畅性。这款软件在经过实际测试后,被认为是非常实用且功能完备的。 ...
四字成语mysql数据30810条
useEnglish 资源E nglish Phrasal Verb & Idiom
AI-Algorithm-Idiom-in-Prolog-Lisp-Java 《Prolog、Lisp 和 Java 中的 AI、Alogirhtm、数据结构和习语》一书的代码
资源来自pypi官网。 资源全名:china_idiom-0.0.2-py3-none-any.whl
iom` (`id`, `guid`, `idiom`, `full_pinyin`, `pinyin`, `az`, `description`, `source`, `idiom_traditional`, `spinyin`, `idiom_phonetic`, `idiom_correct_pronunciation`, `idiom_distinguish`, `idiom_...
* This code is from the book Java Examples in a Nutshell, 2nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-...
### Idiom WorldServer Desktop Workbench 8.1.0.208 使用指南:关键知识点解析 #### 一、概述与快速入门 **Idiom WorldServer Desktop Workbench**是一款专为语言服务提供商(LSPs)和企业翻译部门设计的翻译记忆...
double 和 long 都是 64 位宽,因此对这两种类型的读是分为两部分的,第一次读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但 Java 中 volatile 型的 long 或 double 变量的读写是原子的。...
成语Idiom 是 AngularJS 的新翻译系统,它允许您在当前范围内阅读以提供基于上下文的翻译 - 没有更多的东西,他/她,您实际上知道您在写什么。 #用法向您的项目添加一个文件夹,其中包含每种语言的一个 json 文件...
java 8 lambda Concise syntax – More succinct and clear than anonymous inner classes • Deficiencies with anonymous inner classes – Bulky, confusion re “this” and naming in general, no nonfinal var...
【标题】"猜成语小程序数据库表ims_yf_chengyu_idiom"涉及到的是一个与成语相关的微信小程序的数据存储结构。这个数据库表很可能是用来管理小程序内部的成语信息,包括成语的ID、成语内容、含义、出处等关键数据,以...
"Idiom-看图猜成语程序"是一款基于Python语言开发的应用,旨在提供一种娱乐与学习相结合的方式,让用户通过观察图片来猜测对应的成语。这个程序可能是为教育或休闲目的设计的,利用Python的图像处理和人机交互功能,...
**Pimpl Idiom(指针实现技巧)** 在C++编程中,`Pimpl Idiom`,也称为`Pointer to Implementation`或`Impl Pointer`,是一种设计模式,它用于实现类接口与其实现的分离,以提高代码的编译时间和模块化。这种技术的...
自然语言处理相关的分词数据
This paper conducts a comprehensive investigation based on idiom in four-year series of textbooks of undergraduate and gets the distribution of different grades idioms. We also analyze idioms ...
Idiom idiom = new Idiom(); idiom.setId(cursor.getInt(0)); idiom.setIddiom(cursor.getString(1)); idiom.setExplanation(cursor.getString(2)); // 将成语添加到ListView的适配器中 } while (cursor....
Workspace exploration and idiom hints ?Python mode for Emacs Version 2.6 (What's new?) Check updates at http://rgruet.free.fr/#QuickRef. Please report errors, inaccuracies and suggestions to ...