Barrier Objects in Python

Barrier objects in python are used to wait for a fixed number of thread to complete execution before any particular thread can proceed forward with the execution of the program. Each thread calls wait() function upon reaching the barrier. The barrier is responsible for keeping track of the number of wait() calls. If this number goes beyond the number of threads for which the barrier was initialized with, then the barrier gives a way to the waiting threads to proceed on with the execution. All the threads at this point of execution, are simultaneously released.

Barriers can even be used to synchronize access between threads. However, generally a barrier is used to combine the output of threads. A barrier object can be reused multiple times for the exact same number of threads that it was initially initialized for.

Initializing a barrier

A barrier can be initialized using threading.Barrier class as shown in the program below. The number within the parenthesis represents the number of the threads that the barrier should wait upon.

Syntax:

barrier = threading.Barrier(number_of_threads, action = None, timeout = None)

Create a barrier object for the number_of_threads. An action, when provided, is a callable to be called by one of the threads when they are released. timeout is the default timeout value if none is specified for the wait() method.



import threading

barrier = threading.Barrier(3)

class thread(threading.Thread):
    def __init__(self, thread_ID):
        threading.Thread.__init__(self)
        self.thread_ID = thread_ID
    def run(self):
        print(str(self.thread_ID) + "\n")
        barrier.wait()
        
thread1 = thread(100)
thread2 = thread(101)

thread1.start()
thread2.start()
barrier.wait()

print("Exit\n")



Output:

100
101
Exit

Some common function calls related to threading.Barrier class are:

  1. Checking the state of the barrier:
    broken: A boolean that is True if the barrier is in the broken state.
    Syntax:

    barrier.broken

  2. parties: The number of threads required to pass the barrier.
    Syntax:

    barrier.parties
  3. Aborting a barrier:
    abort: Put the barrier into a broken state. This causes any active or future calls to wait() to fail with the BrokenBarrierError

    Abort function calls on barrier are often required to skip the conditions of deadlocking during program execution.
    Syntax:

    barrier.abort()
  4. Resetting the barrier:
    reset: Return the barrier to the default, empty state. Any threads waiting on it will receive the BrokenBarrierError exception.

    Syntax:

    barrier.reset()
  5. wait: Pass the barrier. When all the threads party to the barrier have called this function, they are all released simultaneously. If a timeout is provided, it is used in preference to any that was supplied to the class constructor.

    The return value is an integer in the range 0 to parties – 1, different for each thread. If the call times out, the barrier is put into the broken state. This method may raise a BrokenBarrierError exception if the barrier is broken or reset while a thread is waiting.

    Syntax:

    barrier.wait(timeout = None)
  6. n_waiting: The number of threads currently waiting in the barrier.
    Syntax:

    barrier.n_waiting

Usually, when either a barrier object is reset or broken down, then the BrokenBarrierError exception is raised.

Here’s a sample program to display how barriers are used in python

# program to demonstrate
# barriers in python

import threading

barrier = threading.Barrier(3)

class thread(threading.Thread):
    def __init__(self, thread_ID):
        threading.Thread.__init__(self)
        self.thread_ID = thread_ID
    def run(self):
        print(str(self.thread_ID) + "\n")
        print("Parties = " + str(barrier.parties) + "\n")
        print("n_waiting = " + str(barrier.n_waiting) + "\n")
        barrier.wait()
        
thread1 = thread(100)
thread2 = thread(101)

thread1.start()
thread2.start()

barrier.wait()

print(str(barrier.broken) + "\n")
barrier.reset()
print("n_waiting after reset = " + str(barrier.n_waiting))
barrier.abort()
print("End")


Output:

100
101
Parties = 3
Parties = 3
n_waiting = 1
n_waiting = 1
False
n_waiting after reset = 0
End

This article is contributed by Mayank Kumar. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

GATE CS Corner    Company Wise Coding Practice





Writing code in comment? Please use ide.geeksforgeeks.org, generate link and share the link here.