-1

内のロックに同期使用することから、ロックダブルチェックを変換するJAVA 8に​​キーワードを使用してロックする次のコード実行のダブルチェックを考えてみましょう:はJAVA

private static void redoHeavyInitialisation() { 
    if (needToReinitialise()) { 
     synchronized (MyClass.class) { 
      if (needToReinitialise()) { 
       doHeavyInitialisation(); 
      } 
     } 
    } 
} 

初期化が重いので、ダブルチェックロックが使用されている理由は、 (したがって、怠け者)、それは複数回起こることがあります(したがって、シングルトンパターンは使用できません。私が間違っていれば修正してください)。

まず、synchronizedキーワードを使用する代わりに、上記のコードをLockを使用してJAVAの同時パッケージからどのように変換しますか?

その後、オプションで、Lockまたはsynchronizedキーワードを使用してコメントすることもできます。

この質問はロックと同期の比較に関するものではありません。コード変換部分に応答しない回答の試みは、受け入れられた回答として選択されません。

+0

可能な重複(http://stackoverflow.com/questions/4201713/synchronization-vs-lock)を実装して延び –

+0

@ErwinBolwidtはい、あなたが比較に集中し、この質問を完全に無視して、主要な質問である同等のコード変換を求めるならば。あなたがしたいと思っていない場合は比較にコメントする必要はありませんが、コードの変換をしてください。 – user1589188

+0

シングルトンを使用できます。考えられるアーキテクチャの1つは、初期化と再開始の同期メソッドを持つSingleton HeavyInitializerクラスを作成することです。 – Chocksmith

答えて

1

ReentrantLockを使用して同期ブロックを等価ブロックに変換するのはかなり簡単です。

まず、ロックしていたオブジェクトと同じスコープと有効期間でロックを作成します。ここではMyClass.classをロックしているので、静的ロックとなるので、これをMyClass.initLockのようなMyClassの静的ロックにマップすることができます。

それからちょうどそれぞれを置き換える:

synchronized (object) { 

すべて一緒にそれを置く

lock.lock(); 
try { 

} finally { 
    lock.unlock(); 
} 

とそれぞれ関連する閉じ括弧とあなたが持っている:

private final static ReentrantLock initLock = new ReentrantLock(); 

private static void redoHeavyInitialisation() { 
    if (needToReinitialise()) { 
     MyClass.initLock.lock(); 
     try { 
      if (needToReinitialise()) { 
       doHeavyInitialisation(); 
      } 
     } finally { 
      MyClass.initLock.unlock(); 
     } 
    } 
} 

パフォーマンス面では、アプローチの間に少し日光があります。基本的に同じセマンティクスを持ち、通常は同様の根底にあるメカニズムを使用します。過去にはパフォーマンスの違いがありました.1つまたは2つのJVMに違いがあるような最適化が行われている場合がありますが、ダブルチェックロックの場合は、だから、最も簡単なことをしてください。 needToReinitialise()メソッドが実行されている間は、非常に短い一時的期間だけロックを取得するので、ロッキング・コストには影響はありません。

+0

ありがとうございます。ほぼ最良の答え。 'ReentrantLock'でなければならない理由についてコメントしてもらえますか?' Lock'の他のバリエーションは使用されていませんか? – user1589188

+0

'ReentrantLock'は、私がJava 8で知っている' Lock'インターフェースの直接的に具体化できる唯一の実装です。他にどのような実装について話していますか? @ user1589188 – BeeOnRope

+0

申し訳ありませんが、私はロックパッケージを意味していました。その他には、読み書き、刻印、ロックサポートなどがあります。 – user1589188

0

次のコードを考えてみましょう:Oracle's docから

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class HeavyInitializer { 
static final Logger logger = LoggerFactory.getLogger(HeavyInitializer.class); 
static HeavyInitializer singleton; 
public static synchronized HeavyInitializer getInstance() { 
    if (singleton==null) { 
     singleton = new HeavyInitializer(); 
    } 
    return singleton; 
} 
boolean initialized; 
private HeavyInitializer() { 
    initialized = false; 
} 

public synchronized void initialize() { 
    if (!initialized) { 
     heavyStuffDoneHere(); 
    } 
} 
public synchronized void reInitilize() { 
    if (needToReinitialise()) { 
     heavyStuffDoneHere(); 
    } 
} 

private void heavyStuffDoneHere() { 
    initialized = true; 
} 

private boolean needToReinitialise() { 
    if (!initialized) 
     return false; 
    boolean ret = false; 
    //Do your check here... and set ret  
    return ret; 
} 

} 

を:

...その後、これらのメソッドが同期することは2つの効果があります。

  • まず、それは2のために可能ではありません同じオブジェクト上に同期メソッドを呼び出してインターリーブします。あるスレッドがオブジェクトの同期メソッドを実行しているとき、そのオブジェクトで最初のスレッドが完了するまで、同じオブジェクトブロックの同期メソッドを呼び出す他のすべてのスレッド(実行を中断)。

  • 第2に、同期化されたメソッドが終了すると、自動的に同じオブジェクトの同期化されたメソッドを呼び出すときに、先行する関係を確立します。これにより、オブジェクトの状態の変更がすべてのスレッドで認識できることが保証されます。

ロックを使用しようとすると、同期ブロックを再実装しようとしています。必要はありません。

+0

私はあなたにスコアを与えることを愛するだろうが、あなたがそこに持っているものは私の質問に例のように '同期 'を使用していますが、私の質問に全く答えません。 – user1589188

+1

代わりのアーキテクチャを提供して提示しようとしています。私の経験では、ロックやセマフォと同期して再実装すると、実行時に解決するのが困難なバグが発生することが示されています。私は、同期シングルトンアーキテクチャを使用します。 – Chocksmith

-1

シングルトンロックをダブルチェックし、シングルトンオブジェクトがシリアライズを使用して中断するのを防ぎます。

package pattern.core.java; import java.io.Serializable;

パブリッククラスシングルトンオブジェクトがシリアライズ{

private static final long serialVersionUID = 1L; 
private static Singleton sg; 

private Singleton() { 
} 

public static Singleton getSingletonObj() { 
    if (sg == null) { 
     synchronized (sg) { 
      if (sg == null) { 
       sg = new Singleton(); 
      } 
     } 
    } 
    return sg; 
} 


/* 
* this method ensures that new object will not be created for singleton 
* class using serialization and deserialization 
*/ 
protected Object readResolve() { 
    return sg; 
} 

/* 
* @Override protected Object clone() throws CloneNotSupportedException { 
* throw new CloneNotSupportedException(); } 
*/ 

@Override 
protected Object clone() throws CloneNotSupportedException { 
    return sg; 
} 

} [ロックVS同期]の

+1

コードを適切にフォーマットしてください – Ibo