What can Semaphore do

Semaphore is used to control the number of threads accessing a particular resource at the same time, coordinating threads to ensure proper use of common resources. Semaphore can be used for flow control, especially in applications where common resources are limited, such as database connections.

How is Semaphore used

Semaphore is primarily used to manage semaphores, and the number of manageable semaphores is set by passing in construction parameters when creating Semaphore object instances. In short, Semaphore managed signals are like tokens that are passed in when constructed, that is, the number of concurrent Semaphore controls. Before executing concurrent code, the thread acquires the signal (aquire acquires the signal permission) and returns the signal after execution (release returns the signal). After each acquire signal is successful, the available Semaphore is reduced by one. The number of Semaphore available semaphores is increased by one, and if the number of semaphores is reduced to zero, the acquire call blocks and Aquire does not get a signal back until the release call releases it.

An example: An application that reads tens of thousands of files can start dozens (say 10) of threads concurrently because they are IO intensive tasks. After reading into memory, the data is stored in the database, but there are only three connections to the database. Semaphore is used to control the number of threads that are connected to the database. If you don’t get an error, you can’t connect to the database.

The limited common resource in this case is the database connection. Java implementation is as follows:

import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; Public class SemaphoreTest {private static final int THREAD_COUNT = 10; private static ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT); Private static Semaphore Semaphore = new Semaphore(3); private static Semaphore Semaphore = new Semaphore(3); Public static void main(String[] args){/* Create a thread to read data and try to get the database connection to store data in the database */for(int i = 0; i < THREAD_COUNT; i++){ final int index = i; Runnable task = newRunnable() {
                public void run() {try {/* Read data from remote */ system.out.println () {try {/* Read data from remote */ system.out.println ()"thread-"+ index + " is reading data from remote host"); Semaphore.acquire (); /* Acquire (); /* Acquire (); System.out.println("thread-"+ index + " is saving data...."); Thread.sleep(10); }catch (InterruptedException e){ e.printStackTrace(); }finally {/* Finally use the semaphore */ semaphore.release(); }}}; executorService.execute(task); }}}Copy the code

The execution result of the above code is shown below:

If Semaphore manages only one Semaphore, it degenerates into a mutex. If there is more than one Semaphore, it mainly controls concurrency. Semaphore is much more granular than controlling concurrency by controlling the number of threads, simply placing the code that controls the most concurrency between Acquire and Release.

CyclicBarrier Guidelines for Concurrent Programming in Java

Java Concurrency CountDownLatch Usage Guide