Semaphore - Synchronization Primitives In Python

Overview:

  • A semaphore is a synchronization construct.
  • Semaphore provides threads with synchronized access to a limited number of resources.
  • A semaphore is just a variable. The variable reflects the number of currently available resources. For example, a parking lot with a display of number of available slots on a specific level of a shopping mall is a semaphore.
  • The value of semaphore cannot go less than zero and greater then the total number of the available resources.
  • The semaphore is associated with two operations – acquire and release.
  • When one of the resources synchronized by a semaphore is "acquired" by a thread, the value of the semaphore is decremented.
  • When one of the resources synchronized by a semaphore is "released" by a thread the value of the semaphore is incremented.
  • The Dutch computer scientist Edsger Dijkstra invented the concept of semaphore.
  • Dijkstra named the two operations on a semaphore acquire and release as p and v using the first letter of the Dutch words proberen and vehogen.
  • The word proberen means test and vehogen means increment in Dutch.

Semaphores in Python

Semaphores in Python:

  • The Semaphore class of the Python threading module implements the concept of semaphore.
  • It has a constructor and two methods acquire() and release().
  • The acquire() method decreases the semaphore count if the count is greater than zero. Else it blocks till the count is greater than zero.
  • The release() method increases the semaphore count and wakes up one of the threads waiting on the semaphore.

Example:

# An example python program using semaphore provided by the python threading module

import threading

import time

 

parkRequests    = 0

removeRequests  = 0

 

parked          = 0

removed         = 0

 

parkedLock      = threading.Lock()

removedLock     = threading.Lock()

 

availbleParkings = threading.Semaphore(10)

 

def ParkCar():

        availbleParkings.acquire()

        global parkedLock

        parkedLock.acquire()

       

        global parked

        parked = parked+1

        parkedLock.release()

 

        print("Parked: %d"%(parked))      

   

def RemoveCar():

        availbleParkings.release()

        global removedLock

        removedLock.acquire()

               

        global removed

        removed = removed+1

        removedLock.release()

        print("Removed: %d"%(removed))       

 

# Thread that simulates the entry of cars into the parking lot

def parkingEntry():

    # Creates multiple threads inside to simulate cars that are parked

    while(True):

        time.sleep(1)

        incomingCar = threading.Thread(target=ParkCar)

        incomingCar.start()

       

        global parkRequests

        parkRequests = parkRequests+1

        print("Parking Requests: %d"%(parkRequests))

 

# Thread that simulates the exit of cars from the parking lot

def parkingExit():

    # Creates multiple threads inside to simulate cars taken out from the parking lot

    while(True):

        time.sleep(3)

        outgoingCar = threading.Thread(target=RemoveCar)

        outgoingCar.start()

 

        global removeRequests

        removeRequests = removeRequests+1

        print("Remove Requests: %d"%(removeRequests))

 

# Start the parking eco-system

parkingEntryThread      = threading.Thread(target=parkingEntry)

parkingExitThread       = threading.Thread(target=parkingExit)

 

parkingEntryThread.start()

parkingExitThread.start()

 

Output:

Parked: 14

Parking Requests: 14

Removed: 5

Remove Requests: 5

Parked: 15

Parking Requests: 15

Parking Requests: 16

Parking Requests: 17

Removed: 6

Remove Requests: 6

Parked: 16

Parking Requests: 18

Parking Requests: 19

Parking Requests: 20

Removed: 7

Remove Requests: 7

Parked: 17

Parking Requests: 21

Parking Requests: 22

Parking Requests: 23

Removed: 8

Parked: 18

Remove Requests: 8

Parking Requests: 24

 

 


Copyright 2023 © pythontic.com