天天看点

Initialization On Demand Holder idiom的实现探讨

这个方案的技术实质是利用java类初始化的lc锁。相比其他实现方案(如double-checked locking等),该技术方案的实现代码较为简洁,并且在所有版本的编译器中都是可行的。该方案代码如下:

<code>1</code>

<code>public</code> <code>class</code> <code>instancefactory {</code>

<code>2</code>

<code>    </code><code>private</code> <code>static</code> <code>class</code> <code>instanceholder {</code>

<code>3</code>

<code>        </code><code>public</code> <code>static</code> <code>instance instance = </code><code>new</code><code>instance();</code>

<code>4</code>

<code>    </code><code>}</code>

<code>5</code>

<code>6</code>

<code>    </code><code>public</code> <code>static</code> <code>instance getinstance() {</code>

<code>7</code>

<code>        </code><code>return</code> <code>instanceholder.instance ;  </code><code>//这里将导致instanceholder类被初始化</code>

<code>8</code>

<code>9</code>

<code>}</code>

<code>01</code>

<code>public</code> <code>class</code> <code>something {</code>

<code>02</code>

<code>    </code><code>private</code> <code>something() {}</code>

<code>03</code>

<code>04</code>

<code>    </code><code>private</code> <code>static</code> <code>class</code> <code>lazyholder {</code>

<code>05</code>

<code>        </code><code>private</code> <code>static</code> <code>final</code> <code>something instance = </code><code>new</code> <code>something();</code>

<code>06</code>

<code>07</code>

<code>08</code>

<code>    </code><code>public</code> <code>static</code> <code>something getinstance() {</code>

<code>09</code>

<code>        </code><code>return</code> <code>lazyholder.instance;</code>

<code>10</code>

<code>11</code>

<code>public</code> <code>class</code> <code>singleton {</code>

<code>    </code><code>// private constructor prevents instantiation from other classes</code>

<code>    </code><code>private</code> <code>singleton() { }</code>

<code>    </code><code>/**</code>

<code>    </code><code>* singletonholder is loaded on the first execution of singleton.getinstance()</code>

<code>    </code><code>* or the first access to singletonholder.instance, not before.</code>

<code>    </code><code>*/</code>

<code>    </code><code>private</code> <code>static</code> <code>class</code> <code>singletonholder {</code>

<code>        </code><code>public</code> <code>static</code> <code>final</code> <code>singleton instance = </code><code>new</code> <code>singleton();</code>

<code>12</code>

<code>13</code>

<code>    </code><code>public</code> <code>static</code> <code>singleton getinstance() {</code>

<code>14</code>

<code>        </code><code>return</code> <code>singletonholder.instance;</code>

<code>15</code>

<code>16</code>

在讨论这个问题前,首先我们需要明确的是,上述三种方案都是可以保证线程安全的。

t is a class and an instance of t is created. t is a class and a static method declared by t is invoked. a static field declared by t is assigned. a static field declared by t is used and the field is not a constant variable (§4.12.4). t is a top level class (§7.6), and an assert statement (§14.10) lexically nested within t (§8.1.3) is executed.

只有基本类型或者是string类型的变量,才可能成为constant variable。

回到刚才的问题,在stackoverflow上有相关问题的回答。

首先,关于final关键字:

<a href="http://stackoverflow.com/questions/20995036/is-initialization-on-demand-holder-idiom-thread-safe-without-a-final-modifier">http://stackoverflow.com/questions/20995036/is-initialization-on-demand-holder-idiom-thread-safe-without-a-final-modifier</a>

根据该问题的两个回答,不论有无final关键字,事实上都可以保证线程安全,final关键的作用仅在于防止对instance做修改。

然后是关于instance的访问权限问题:

<a href="http://stackoverflow.com/questions/21604243/correct-implementation-of-initialization-on-demand-holder-idiom">http://stackoverflow.com/questions/21604243/correct-implementation-of-initialization-on-demand-holder-idiom</a>

这里提出的观点是建议如下形式的实现:

<code>    </code><code>...</code>

<code>        </code><code>static</code> <code>final</code> <code>singleton instance = </code><code>new</code> <code>singleton();</code>

即并不在instance变量前添加public或者private修饰,即使用默认的package private访问权限。

不用public的原因是这个修饰不够合理,作者认为事实上在lazyholder是被限定为private的情况下,使用public来修饰instance并没有问题,然而如果有人修改lazyholder为public,那么就可能出现问题。

otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.

所以外部类拥有对内部类中private字段的访问权限,那么在这个情况下,编译器就会有一些小技巧来保证外部类对内部类private字段的访问权限,即在内部类中插入packge private method,使得外部类调用这些getter和setter方法的形式来访问内部类的private字段。

综上所述,从线程安全的角度而言,上述的几种“initialization on demand holder idiom”实现都是没有问题的。如果讨论细节上的合理性,那么更推荐最后一种实现,即:

<a href="http://ifeve.com/initialization-on-demand-holder-idiom/#viewsource">查看源代码</a>

继续阅读