Topics

Barrier Object

Welcome to a tutorial on Barrier objects. Here you learn about barrier objection and how it can be used.

The barrier object is created by using the Barrier class that is readily available in the threading module, and the object can be used in situations where we want a given set of threads to wait for each other.

Now, suppose, we have two threads, and we want two threads to execute when both are ready. In this case, the threads will call the wait() method on the barrier object immediately after they are ready and they will be released concurrently when both of them have called the wait() method only.

Below is the general syntax of the barrier class to initialize a barrier object.

threading.Barrier(parties, action=None, timeout=None)

 

Thus, the parties specify the number of threads waiting at the barrier; action is used to specify a function that will be executed by any other thread waiting for the barrier, and timeout is used to specify a timeout value in seconds for which the barrier will be released from all the waiting threads.

 

Functions provided by Barrier class

Below are the functions provided by the Barrier class:

 

wait(timeout=None) method

If during programming and we desire a set of threads to wait for each other, then, we have to initialize the barrier object with the number of threads specified as parties parameter during barrier object creation. After which the barrier will be released only when the same number of threads call the method wait() of the barrier object.

However, in a thread when the timeout value is provided while calling the wait() method, then that thread will get released from the barrier immediately after the timeout time is passed.

In addition, the methods are usually 0 to parties-1, and these values can be used to identify the threads that have reached the waiting point of the barrier and which all are still not there. 

Check out the example below.

i = barrier.wait()
if i == 0:
    # Only one thread Will be allowed to print this
    print("0th thread passed the barrier")

 

From the example, the return value of the wait() method can be used for carrying out some clean-up task, e.g. suppose 3 threads are doing some work and using a temporary file to store data, and immediately after the thread is done, we can put a check on the wait() method that when the last thread reaches its waiting point and the barrier is to be released before that delete the file.

i = barrier.wait()
if i == 2:
    # delete the temporay file

Now, when the wait call times out, the barrier is put into a broken state.

In addition, the wait() method may raise a BrokenBarrierError if the barrier breaks or resets as a thread waits.

 

reset() method

This function typically resets the barrier to its default, empty state. Also, if threads are waiting for the barrier to get released will receive BrokenBarrierError.

 

abort() method

The abort() method when called on a barrier puts it into a broken state. Once this method is called by any of the waiting threads, the rest of the threads waiting for the barrier to be released will receive BrokenBarrierError.

During programming, we may decide, to use this method in case of some deadlock situation to release the waiting thread.

 

parties

This method typically returns the number of threads we need to pass the barrier.

 

n_waiting

This method returns the number of threads that are currently waiting for the barrier to be released.

 

broken

It is a Boolean value that is True if the barrier is in the broken state.

 

Example on Barrier Object

In the example below, there are two threads representing server and client in which the client thread will wait for the server to get ready before sending any request to it.

import threading
import time

def start_server():
  # starting server
  print("starting the server...")
  # do some startup work
  time.sleep(2)
  

def server(b):
    start_server()
    b.wait()
    print("Server is ready.")

def client(b):
    print("waiting for server getting ready...")
    b.wait()
    print("sending request to server...")

if __name__=='__main__':
  
  b = threading.Barrier(2, timeout=5)
  # server thread
  s = threading.Thread(target=server, args=(b,))
  s.start()
  # client thread
  c = threading.Thread(target=client, args=(b,))
  c.start()

  s.join()
  c.join()
  print("Done")

Output:

starting the server...waiting for server getting ready...

Server is ready.
sending request to server...
Done

From the above example, call the abort() method in either client or server and check out what happened. Also, there might be a need for you to use the try block to catch the BrokenBarrierError in the program.