気軽に楽しくプログラムと遊ぶ

自分が興味があってためになるかもって思う情報を提供しています。

Java クラスをスレッドセーフに実装する

スレッドセーフを意識する必要がある処理

  • 同時アクセス処理
  • スレッド処理

アンスレッドセーフなコード

複合アクションにおいて複数のスレッドが割り込むと正しい動作が保証できない。

複数アクションには以下の二つがある。
・リード・モディファイ・ライト操作
・チェック・ゼン・アクト操作

リード・モディファイ・ライト操作

リード・モディファイ・ライト(read-modify-write,読んで/変更して/書き戻す)操作

public class Sequence {
    private int value = 1;

    public int getValue() {
        return value - 1;
    }

    public int getAndIncrement() {
        return value++;  // リード・モディファイ・ライト操作
    }

}

value++の操作
・現在の値を読む -> この値がリターンされる
・その値に1を加える
・その新しい値を書きこと

チェック・ゼン・アクト操作

チェック・ゼン・アクト(check-then-act ステートをチェックしてからその結果に基づいて行為する)です。

public class Cache {
    private static Cache instance;
    public static Cache getInstance() {
        if ( instance == null ) { // チェック・ゼン・アクト操作
            instance = new Cache();
        }
        return instance;
    }
    private    Cache(){
    }
}

スレッドセーフな実装

スレッドセーフにするには、これらの操作をアトミックに実行(一連の動作を割り込みなしで実行)できるようにする必要がある。

以下のような形で行う。

public class Cache {
    private static Cache instance;
    public static Cache getInstance() {
        synchronized (instance) { // instanceでロックする
            if ( instance == null ) { // チェック・ゼン・アクト操作
                instance = new Cache();
            }
        }
        return instance;
    }
    private    Cache(){
    }
}

参考URL

スレッドセーフにするために考えること 〜基礎編〜 - じゅんいち☆かとうの技術日誌