What is a semaphore, and when to use it?
In Java's concurrency API, a semaphore is another synchronization tool that simultaneously controls the number of threads accessing a particular resource or section of code. It manages a set of permits; threads must acquire a permit before proceeding. If a permit is available, the thread acquires it and continues execution. If not, the thread is blocked until a permit becomes available or interrupted. The Semaphore class in Java offers two primary methods: acquire() and release().
Let's assume a database that can only endure ten connections simultaneously. With the advent of Virtual Threads in JDK 21, creating many threads has become relatively easy and cheap. This becomes a double-edged sword for this particular case, as many threads can attempt to connect in this database simultaneously, and this can overwhelm the database.
Here is our MockDatabase class:
To avoid overwhelming the database, we can employ a semaphore to limit concurrent access. Below is the modified MockDatabase class with a Semaphore:
To ensure that the semaphore is effectively limiting the database connections to ten, we can create a JUnit test. The test will utilize an AtomicInteger to count the maximum number of concurrent calls to the getConnection() method and verify that it never exceeds ten.
In conclusion, Java's Semaphore class offers a robust and straightforward mechanism for controlling access to limited resources in a concurrent environment.