2.2 Atomicity アトミック性

  • たとえばステートレスなサーブレットにカウンターをあらわす変数を追加するとスレッドセーフではなくなる。
    • この例では同時に2つのスレッドがアクセスしたとき、初期値が9だったら、片方は10でもう片方は11を返さなければならないが、10になってしますかもしれない。

2.2.1 Race Condition (レース状態)

  • レース状態の具体例としては大学通りにあるスターバックスに2人に待ち合わせたが、大学通りにはスターバックスが2つあって、どっちなんだろうと2人が行ったりきたりするのが挙げられる。
  • 例のようになにかがtrueであることを確かめてから、それにもとづくアクションを起こすような処理において、想定する動作にならないレース状態は「check-then-act」と呼ばれる。

2.2.2 Exapmles:race conditions in lazy initialization

  • 「lazy initialization」とはインスタンスが必要となるときまで、インスタンス生成を延期すると同時にたった一度だけ再生されることを保障すること。
  • LazyInitRaceクラスはrace condition状態である。
  • アプリケーションでの登録処理でのインスタンス生成にLazeyInitRaceクラスを使用するならば、ある登録処理が失われる可能性がある。
  • UnsafeSequenceをエンティティの識別のためのIDを振るために使用するならば、同じIDのものが存在してしまう危険性がある。同じシーケンスを作成するインスタンスを生成するためのクラスが2つ存在してしまう可能性もある。

2.2.3 Compound actions

  • レース状態を避けるために変数の値を変更している途中のスレッドをほかのスレッドから邪魔されなくする必要がある。

AとBの操作がアトミックであるとは
あるスレッドがAを実行するときに
違うスレッドがBを実行する、実行してしまった、Bを実行していない
のどの状況にもお互いに協調している。
つまりアトミックな操作とは自分自身と同じような
ステータスに実行されうる全ての操作と協調していることである。

  • UnsafeCountingFactorizerクラスはlong型の変数ではなく、java.util.concurrent.atomicパッケージのAtomicLongクラスを使用すればよい。

クラスの状態を管理するにはAtomicLongのようにすでに用意されている
スレッドセーフなオブジェクトを使用するのがよい。
きまぐれな状態変数よりもスレッドセーフなオブジェクトを保持するほうが、
起こりうる状態や状態遷移において理にかなっていて、より簡単である。
またこのようなほうがスレッドーセーフを維持管理しやすい。