educative.io

Educative

How to get semaphores work for multiple printers in the printer example?

Trying to get the printer example work with Semaphore and multiple printers? So far, I get the print out correct, but the program hung at the end. It works for single printer case. What is missing in the code snippet below?
from threading import Lock, Thread, Condition, current_thread, Semaphore
import time

def find_prime():
    global found_prime
    global prime_num
    num = 2
    while not exit_main:
        while not is_prime(num):
            num += 1
            #NOTE: add a timer to slow down the thread so that we may see the process in progress
            time.sleep(0.01)
        prime_num = num
        # notify the printer thread once a prime number has been found
        sem_find.release()
        # wait for printer thread to complete printing the prime number
        sem_print.acquire()
        # increment i when i is a prime
        num += 1


def is_prime(num):
    if num == 2 or num == 3:
        return True
    factor = 2
    while factor * factor <= num:
        if num % factor == 0:
            return False
        factor += 1
    return True


def print_prime():
    global prime_num
    global found_prime
    while not exit_main:
        # wait for notification when a prime is found
        sem_find.acquire()
        if not exit_main:
            print(f"{current_thread().getName()} prints {prime_num}")
            found_prime = False
        sem_print.release()


if __name__ == "__main__":
    sem_find = Semaphore(0)
    sem_print = Semaphore(0)
    found_prime = False
    prime_num = None
    exit_main = False
    finder_thread = Thread(target=find_prime)
    finder_thread.start()
    # printer_thread = Thread(target=print_prime)
    # printer_thread.start() 

    #TODO: why Semaphore does not work for multiple printers??
    printer_thread = Thread(target=print_prime)
    printer_thread.start()
    printer_thread2 = Thread(target=print_prime)
    printer_thread2.start()

    # Let other threads run for x seconds before exit the program
    time.sleep(0.1)
    exit_main = True
    printer_thread.join()
    printer_thread2.join()
    finder_thread.join()