ダブル・チェック・ロッキング

提供: MonoBook
2012年9月30日 (日) 10:09時点におけるimported>Piyoによる版 (→‎Java)
ナビゲーションに移動 検索に移動

ダブル・チェック・ロッキング(英語:Double Check Locking)とは、初回はロックなしで状態チェックを行い、そこで必要であれば再度ロックを掛けたのちに状態チェックを行うというソフトウェア最適化技法、デザインパターンのひとつである。

ロックは非常にオーバーヘッドの大きい重い処理であるため、その発生回数を可能な限り減らすことで高速化を実現しようというものである。

ダブル・チェック・ロッキングは、主にマルチスレッド環境下でのシングルトンパターンを実装する際にオーバーヘッドの低減を目的として使われることが多い。

主なプログラミング言語での実装例

C#

C#における標準的なダブル・チェック・ロッキングの実装方法を示す。この記述方法ではC#のキーワードのひとつであるvolatileを用いているのがミソである。なおvolatileキーワードと同等の機能を提供していない.NET Framework系のプログラミング言語も多く、それらでは別の実装方法を検討する必要がある。

public class MySingleton
{
    private static object _sync = new object();
    private static volatile MySingleton _instance = null;

    // プライベートコンストラクター
    // ※本クラスを除き、newキーワードによるインスタンス生成を出来なくする。
    private MySingleton()
    {
    }

    // 
    public static MySingleton GetInstance()
    {
        // 1回目のチェック
        // ロックしていないので高速に処理される
        if (null == _instance)
        {
            // ロック
            // ※このブロック内はクソ重い
            lock (_sync)
            {
                // 2回目のチェック
                if (null == _instance)
                {
                    _instance = new MySingleton();
                }
            }
        }
        return _instance;
    }
}

C# (Lazy)

.NET Framework 4.0では、標準でLazy<T>クラスが用意されており、それを使うことでよりシンプルにダブル・チェック・ロッキングを記述できるようになった。 この記述方法はC#に依存した機能も特に使われておらず、.NET Framework系の様々なプログラミング言語へも特に悩むことなく移植・実装可能であると思われる。

using System;

public class MySingleton
{
    private static readonly Lazy<MySingleton> _instance  
        = new Lazy<MySingleton>(() => new MySingleton());

    private MySingleton()
    {
    }

    public static MySingleton GetInstance()
    {
        return _instance.Value;
    }
}

Java

Javaでは仕様においてアウトオブオーダーを用いるメモリモデルが可能となっていたため、このイディオムを使うことには問題があり、一部の実装では実際に正しく働かない可能性があることが知られている。 http://www.ibm.com/developerworks/jp/java/library/j-dcl/ を参照。

関連項目

参考文献

外部リンク