Introduction
This is a second post of the synchronization primitives series. In the previous post you can read about the Interlocked class primitive. In this post I describe and present an example regarding the Barrier class – another interesting synchronization primitive that .NET offers.
Barrier class
The Barrier class is an IDisposable and non-static class that enables multiple tasks to cooperatively work on an algorithm in parallel through multiple phases (as in the definition in docs) . Once you create a Barrier class object you can access its all public and protected members (apart from the Dispose method) in a thread-safe manner (docs).
Usage scenario of the Barrier class can look like this:
- Create a Barrier object by passing arguments to a constructor:
- participantCount – how many threads participate in a phase.
- postPhaseAction (optional) – an action that is invoked after each phase.
- Define an algorithm consisting of multiple phases. Ideally each phase should be executed in parallel by multiple threads. If a thread finishes its job in a phase it invokes one of the SignalAndWait overload – it means “The thread finished and waits for other threads to finish so that a phase can be finished”. Phase (N+1) can not be started if the Phase N is not finished.
- Define N threads and start the algorithm.
Let me show the real code example to ease the understanding of the steps.
Example
Let’s define a problem to solve: “You are asked to find 7 Guids so that the two leading bytes of SHA256 of each Guid are zeros and store the Guids and hashes in a collection. Then find another 7 different Guids so that the three leading bytes of SHA256 of each Guid are zeros and store the Guids and hashes in another collection”.
As you can see the probles consist of two phases:
- Find 7 Guids so that hashes have two leading zeros,
- Find another 7 Guids so that hashes have three leading zeros.
Moreover, you can figure out that each phase can be processes by 7 independent threads. Each thread tries to find and store its own Guid and corresponding hash in the first phase and then in the second phase:
Once the problem is defined let’s jump to the code.
Create a Barrier object:
Define an algorithm consisting of multiple phases:
Define N threads and start the algorithm:
If you run the program you would see the following output (it might take ~1 minute to compute second collection of hashes so be patient):
As you can see the first phase (Phase0) started and computed all 7 hashes with two leading bytes equal zero (2 zero bytes equals “0000” in hex hence there is “0000” in Phase0 and “000000” in Phase1). Once the Phase0 is finished the Phase1 started and computed its own 7 hashes with three leading bytes equal zero.
Summary
In this post I presented and explained the Barrier synchronization primitive in the .NET environment. The API of the Barrier class consists of members I did not mention in the post (see Properties and Methods sections) and I strongly encourage you to give it a try on your own. As always you can find source code on my GitHub repository.
Have a nice day, bye!
Be First to Comment