Monday, August 01, 2011

Java 7's j.u.c.Phaser - a short tutorial

If you've tried to figure out how the Phaser works in Java 7 and haven't had much luck, then you are not alone. I too had some difficulty understanding what looks like a very esoteric concurrency construct. I asked around on the Concurrency-Interest forum. Folks there are very helpful and I almost understood it but was missing some details.

So, I decided to get my hands dirty and play with this new toy. Phaser (as the JavaDocs say) is very much like a CountDownLatch or a CyclicBarrier but is better suited where:

  1. Parallel operations need to proceed in lockstep
  2. After every step, all parallel operations wait until all others have completed
  3. When they do, all proceed to the next step and so on...
Sounds easy, but understanding the API was not easy for me. So, I had to write a simple program to see how it worked. Here it is:


What the program does is:
  1. Create a Phaser instance and set it up to expect 2 parties and the main thread/itself as a third party
  2. Start 2 producer threads
  3. Start a consumer thread
  4. Unregister itself as the third party and let the 2 producers run in parallel - as 2 remaining parties
  5. In the mean while the 2 producer threads pretend to do some work and move forward in phases
    1. There are a total of 10 phases
    2. Each producer writes it results into an array where the array position matches the phase number
    3. I call this array per producer - a lane (like a highway)
  6. While the producers are running, the consumer tries to catch up with them
    1. It waits for the phase to complete and then reads the results of that phase
    2. The consumer is slower and over time it trails behind the producers
    3. When it comes back after pretending to do some processing the producers would've moved - sometimes 1 or even 2 phases ahead
    4. The consumer now reads all the phases that have completed so far and then catches up
  7. This consumer looks like it is reading "read-committed" transactions - doesn't it? 

This picture (hopefully) explains more clearly, what is happening in the code:

(Remember - the sequence diagram and log shown here are specific to my computer. On slower or faster machines you might see slightly different results - for the consumer, at least in the beginning phases.)
































The log output:


Until next time!


5 comments:

Mohan Radhakrishnan said...

Good attempt at introducing the newer features. I do ask questions on that list too but mine are more basic.

I am trying to figure out FJ to start with. I am also planning to buy time on GAE for example to run on multiple cores. I think I have to use my credit card. If it is not too expensive and I have enough information I will present some details at a small conference in bangalore.

Mohan Radhakrishnan said...

Good attempt at introducing these hard features. I do ask questions on this list too.

Currently I am trying to figure out FJ. I was planning to run the samples on the cloud if I am able to afford it.

Justin Rosenberg said...

Why did you start the sleep method with a dollar sign ($)? I believe you couldn't do this before Java SE 7, but does it provide any different functionality or is it a new naming standard?

Ashwin Jayaprakash said...

It's just a naming convention I follow - I usually keep such public-static helper methods in a separate class.

Starting a method or variable name with $ or _ is legal syntax in Java....from the beginning.

And since public-static methods can be static-imported from Java 5 onwards, I start such method names with a $ to make it easier for readers to understand that the method has been imported from another class. In this example, it's all in the same single class - not of much use.

Cheers!

Unknown said...

Good attempt at introducing these hard features. I do ask questions on this list too.