Semaphores are often used to guard resources with limited capacity, for example, a database server. In any situation where the size of the resource size is fixed, you should use a bounded semaphore. Before spawning any worker threads, your main thread would initialize the semaphore:
maxconnections = 5 ... pool_sema = BoundedSemaphore(value=maxconnections)
Once spawned, worker threads call the semaphore's acquire and release methods when they need to connect to the server:
pool_sema.acquire() conn = connectdb() ... use connection ... conn.close() pool_sema.release()
The use of a bounded semaphore reduces the chance that a programming error which causes the semaphore to be released more than it's acquired will go undetected.
See About this document... for information on suggesting changes.