yohhoyの日記

2014-02-25

java.util.concurrent.Phaser同期プリミティブ

Java 7で追加された java.util.concurrent.Phaser*1 同期プリミティブについてメモ。

Phaser(フェイザー)クラスは、Java 1.5からあるCountDownLatchCyclicBarrierを機能的に包含し、さらに汎用化したスレッド同期プリミティブである。CountDownLatch, CyclicBarrier, Phaserの機能比較を下表に示す。

CountDownLatchCyclicBarrierPhaser
スレッド数固定固定動的変更可
再利用×(1回のみ)
先行可能×(同期バリア)
階層化××
Fork/Join統合××
スレッド数
同期対象となるスレッド数の指定方法。CountDownLatchとCyclicBarrierはオブジェクト構築時に指定し、以降の変更は出来ない。Phaserはオブジェクト構築後に管理スレッド数増減が可能。
再利用
一度同期処理(awaitメソッド)が行われたオブジェクト上で、再びスレッド間同期が可能か否か。CountDownLatchはオブジェクトあたり一回しか利用できない。CyclicBarrierは名前の通り循環式同期バリアのため、任意回の再利用が可能。Phaserは内部状態として「phase(フェイズ)」「終了状態」を持ち、オーバーライド(onAdvanceメソッド)によりユーザが制御することで再利用となる。
先行可能
同期プリミティブへの通知/待機処理のうち、通知処理のみを行えるか否か。CyclicBarrierでは通知・待機処理は不可分。CountDownLatch, Phaserは通知処理のみを行うメソッドが提供される。
階層化
CountDownLatch, CyclicBarrierには階層化の概念はない。Phaserオブジェクトではオブジェクト構築時に親子関係を設定でき、同期対象スレッドのサブグループ化によるスケーラビリティ改善が可能。
Fork/Join統合
Java 7で追加されたFork/Joinフレームワークとの親和性。CountDownLatch, CyclicBarrierでは特に考慮されず、待機中スレッドはブロックされたままとなる。Phaserの待機処理(await系メソッド)では、待機中スレッドにて他の実行可能ForkJoinTaskが処理されうる。

関連URL