See Also: Phaser Members
A reusable synchronization barrier, similar in functionality to Java.Util.Concurrent.CyclicBarrier and Java.Util.Concurrent.CountDownLatch but supporting more flexible usage.
Registration. Unlike the case for other barriers, the number of parties registered to synchronize on a phaser may vary over time. Tasks may be registered at any time (using methods Phaser.Register, Phaser.BulkRegister(int), or forms of constructors establishing initial numbers of parties), and optionally deregistered upon any arrival (using Phaser.ArriveAndDeregister). As is the case with most basic synchronization constructs, registration and deregistration affect only internal counts; they do not establish any further internal bookkeeping, so tasks cannot query whether they are registered. (However, you can introduce such bookkeeping by subclassing this class.)
Synchronization. Like a CyclicBarrier, a Phaser may be repeatedly awaited. Method Phaser.ArriveAndAwaitAdvance has effect analogous to CyclicBarrier.Await. Each generation of a phaser has an associated phase number. The phase number starts at zero, and advances when all parties arrive at the phaser, wrapping around to zero after reaching Integer.MAX_VALUE. The use of phase numbers enables independent control of actions upon arrival at a phaser and upon awaiting others, via two kinds of methods that may be invoked by any registered party:
Termination. A phaser may enter a termination state, that may be checked using method Phaser.IsTerminated. Upon termination, all synchronization methods immediately return without waiting for advance, as indicated by a negative return value. Similarly, attempts to register upon termination have no effect. Termination is triggered when an invocation of onAdvance returns true. The default implementation returns true if a deregistration has caused the number of registered parties to become zero. As illustrated below, when phasers control actions with a fixed number of iterations, it is often convenient to override this method to cause termination when the current phase number reaches a threshold. Method Phaser.ForceTermination is also available to abruptly release waiting threads and allow them to terminate.
Tiering. Phasers may be tiered (i.e., constructed in tree structures) to reduce contention. Phasers with large numbers of parties that would otherwise experience heavy synchronization contention costs may instead be set up so that groups of sub-phasers share a common parent. This may greatly increase throughput even though it incurs greater per-operation overhead.
In a tree of tiered phasers, registration and deregistration of child phasers with their parent are managed automatically. Whenever the number of registered parties of a child phaser becomes non-zero (as established in the Phaser(Phaser, System.Int32) constructor, Phaser.Register, or Phaser.BulkRegister(int)), the child phaser is registered with its parent. Whenever the number of registered parties becomes zero as the result of an invocation of Phaser.ArriveAndDeregister, the child phaser is deregistered from its parent.
Monitoring. While synchronization methods may be invoked only by registered parties, the current state of a phaser may be monitored by any caller. At any given moment there are Phaser.RegisteredParties parties in total, of which Phaser.ArrivedParties have arrived at the current phase (Phaser.Phase). When the remaining (Phaser.UnarrivedParties) parties arrive, the phase advances. The values returned by these methods may reflect transient states and so are not in general useful for synchronization control. Method Phaser.toString() returns snapshots of these state queries in a form convenient for informal monitoring.
Sample usages:
A Phaser may be used instead of a CountDownLatch to control a one-shot action serving a variable number of parties. The typical idiom is for the method setting this up to first register, then start the actions, then deregister, as in:
One way to cause a set of threads to repeatedly perform actions for a given number of iterations is to override onAdvance: If the main task must later await termination, it may re-register and then execute a similar loop:
Related constructions may be used to await particular phase numbers in contexts where you are sure that the phase will never wrap around Integer.MAX_VALUE. For example:
To create a set of n tasks using a tree of phasers, you could use code of the following form, assuming a Task class with a constructor accepting a Phaser that it registers with upon construction. After invocation of build(new Task[n], 0, n, new Phaser()), these tasks could then be started, for example by submitting to a pool: The best value of TASKS_PER_PHASER depends mainly on expected synchronization rates. A value as low as four may be appropriate for extremely small per-phase task bodies (thus high rates), or up to hundreds for extremely large ones.
Implementation notes: This implementation restricts the maximum number of parties to 65535. Attempts to register additional parties result in IllegalStateException. However, you can and should create tiered phasers to accommodate arbitrarily large sets of participants.