2013-03-19 22 views
6

私はシングルトンの場合、ネストされたとの二倍nullの場合、開発者は常にチェックしているいくつかのコード、渡って来ている - 以下のコードのように:私は Java - シングルトンが2回ヌルであるかどうかを調べる理由はありますか?

...

private static processManager singleton = null; 

public synchronized static processManager getInsatnce() throws Exception { 

    if(singleton == null) { 
     if(singleton == null){ 
      singleton = new processManager(); 
     } 
    } 
    return singleton 
} 
をこれが何であるかはわかりませんが、コードには多数のインスタンスが存在するため、理由があると考えられていますか?

+6

2フェーズロックで失敗したようです。最も内側の 'if'ステートメントが' synchronized'ブロック内にあった場合、それは意味をなさないでしょう。 – toniedzwiedz

+0

ええ、私はマルコの答えを見ています。面白い! – Sanchit

+0

http://ja.wikipedia.org/wiki/Double-checked_locking? – mbatchkarov

答えて

15

あなたのコードでは大文字と小文字が正しく示されていません。それover hereについての記事を読む

// 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; 
} 

:これは理にかなっていダブルチェックイディオム、に由来します。

このイディオムは、のインスタンスフィールドの場合にのみ適していることに注意してください。 怠惰initialionホルダークラスイディオム:

// Lazy initialization holder class idiom for static fields 
private static class FieldHolder { 
    static final FieldType field = computeFieldValue(); 
} 
static FieldType getField() { return FieldHolder.field; } 
0

シングルトンがどのプロパティでない限り、これは任意のローミングサービスをしないあなたの質問では、はるかに単純なイディオムが主な選択であり、その場合のためにstaticフィールドを、持っていますゲッターにインスタンスを作成しますが、それでもこれは意味をなさないでしょうし、残りのコードは到達不能になります。

2

私はあなたがDouble Checked Lockingを参照していると思います。このパターンを使用すると、必要がない場合に同期を回避できます。

あなたのコードは、だから我々はシングルトンがnullでないことを確認しているときに我々は唯一の同期、私たちはその後、誰かがすでにそれを構築し始めているだけの場合には再確認を参照

private static volatile ProcessManager singleton = null; 

public static ProcessManager getInstance() throws Exception { 

    if (singleton == null) { 
     synchronized (MyClass.class) { 
      if (singleton == null) { 
       singleton = new ProcessManager(); 
      } 
     } 
    } 
    return singleton; 
} 

でなければなりません。これがシングルトンを動作させるためではないvolatileでなければなりません。 Hereは、volatileを忘れた場合に発生する微妙な問題を説明する記事です。

あなたのケースでは、メソッドが同期されている場合、あなたは正しいです。 2回チェックする必要はありません。

2

Double Checked Locking Idiomを達成しようとして失敗しました。最初のnullチェックは、インスタンスがすでに作成されているかどうかを確認し、それがnot nullである場合は、すでに作成されたインスタンスを返します。

しかし、条件チェックはチェック当時行為状況で、安全なスレッドではないあるので、2つの以上のスレッドがnullとして値を参照してシングルトンの2つのインスタンスを作成する可能性がありますそしてthats doubletonまたは多分ManyTon

したがって、​​を使用して、1つのスレッドだけがそのブロックに入り、1つのインスタンスだけが作成されるようにします。

+0

Double Checked Locking Idiomに関する優れた説明。 – Deepak

+0

したがって、メソッドが同期されているため、おそらくダブルチェックロックを使用する必要はありませんか? –

+0

メソッドをシングルトンにしておくと、関係が起こる前に作成されるため、単一のヌルチェックしか持たなくてもかまいません。注:このメソッドは、クラスをロックするため、不正に実行されます。ですから、メソッドを同期させずに、他の答えですでに述べたテクニックを使用する方がいいです。 –

0

このテクニックはダブルチェックと呼ばれます。

貼り付けたコードは間違っています。あなたは正しいのですが、そのようにヌル値を二重にチェックするのは意味がありません。

private static volatile ProcessManager instance = null; 

public static ProcessManager getInstance() { 
    if (instance == null) { 
     synchronized(ProcessManager.class) { 
     if (instance == null) { 
      instance = new ProcessManager(); 
     } 
     } 
    } 
    return instance; 
} 

2番目のヌルチェックは、ProcessManager.classオブジェクトで同期されていることに注意してください。 getInstance()メソッドは静的メソッドなので必要です。

+1

インスタンスがvolatileでない限り、これは私には壊れています。インスタンス 'if(instance == null)'の最初の読み込みは同期されません。 – assylias

+0

はい、あなたは正しいです。 –

関連する問題