In previous articles, we have covered a lot of underlying principles, technologies and new concepts. In this article, we will take a lighter look at three framework tool classes based on these underlying principles.

They are:

  • The signal Semaphore
  • CountDownLatch
  • Barrier CyclicBarrier

Therefore, since it is a tool class, it must be inseparable from a specific scene, so there is no superior or inferior, only who is more appropriate.

The signal Semaphore

What kind of usage scenarios can Semaphore be used for? Let’s take a common example:

If there is a parking lot with only ten parking Spaces in it, when all ten parking Spaces are occupied, cars outside are not allowed to enter and have to wait outside. One car out, one car in

This scenario is different from our normal concurrent scenario, where only one thread can access a critical resource while the other threads wait.

However, there is a scenario where a critical resource allows multiple threads to access it at the same time, and more than a limited number of additional threads have to block and wait.

This scenario is also possible using the original set, but it’s called “building the wheel,” and the Java Concurrency framework provides a utility class for this scenario.

Semaphore is a utility class for this scenario. Let’s write a demo that implements this logic:

After executing the program, you should see:

You see, one thread out allows one thread in, and that’s Semaphore.

If you look at semaphore’s source code, you will find that it is very similar to our implementation of ReentrantLock, including fair and unfair policy support, except that the state of AQS in the former implementation is generally less than or equal to one (except for ReentrantLock). The state of the latter is less than or equal to ten, which records the number of remaining available critical resources.

So semaphore has an inherent problem: if a thread reentrant a critical section, does the number of available critical resources need to be reduced?

There are ten parking Spaces in the parking lot. A car enters and occupies one parking space. After a period of time, the car reports to the manager that I still need to occupy one parking space.

In fact, in the view of the Java administrator, a thread that has entered a critical section is a “master” and will give priority to any request it makes, even if its own resources are not released.

Therefore, in Semaphore, it is possible for a thread to enter a critical section and then consume all critical resources.

CountDownLatch

The name “CountDownLatch” sounds very advanced. What kind of functions does CountDownLatch provide?

Here’s a common scenario:

Pinduoduo, which is often used by people in daily life, requires at least two or three people to make a group before the merchant can deliver a product.

We won’t go into the business model here, but regardless of how it monetized, it’s just one scenario that, if implemented using a basic concurrency API, you might think:

A thread blocks once and wakes up until the specified number is reached

Yes, that’s right. The inside of the CountDownLatch is implemented like this. The wheels have been built for you.

Run it a few times, and you’ll find that the results won’t be wrong. The order of people may be different, but the merchant must ship the goods after all three people are ready.

In addition, it has more applications, such as 100-meter race, only when all the athletes are ready, the referee will blow the whistle, and so on.

The implementation principle is basically similar to explicit lock, but the difference is that state is controlled. CountDownLatch only determines whether state is equal to zero. If state is not equal to zero, it will block the current thread.

Each call to the countDown method reduces the countDown resource by one count until it reaches zero before waking up the blocked thread.

CyclicBarrier

Cyclicbarriers are very similar to countdownlatches. We will introduce cyclicbarriers first and then compare their differences and similarities with you.

Consider this scenario:

The apartment bus always filled a busload of people downstairs, set off and drove to the subway station, and then returned to pick up another train.

In such a scenario, we consider how to achieve:

It looks something like this:

A CyclicBarrier is like a barrier in that it takes two parameters to instantiate it. The first parameter specifies how many threads our barrier will block before it opens, and the second parameter specifies what additional operations the last thread to reach the barrier needs to do.

In general, when the last thread reaches the barrier, the barrier opens, freeing all previous threads and closing the barrier again at the end.

CyclicBarrier only needs to use an await to complete all functions. Let’s summarize the implementation logic of this method:

  1. First, reduce the number of resources available at a time
  2. If the number of available resources is zero, then we are the last thread, so we do the extra action we pass, wake up all the threads that have arrived and are waiting, and restart a barrier count.
  3. Otherwise, it means that it is not the last thread, so it blocks on a conditional queue in a loop

Ok, after looking at CyclicBarrier, you will find that it is really similar to our countdown door latch, and we will explain the difference and connection between them.

The first difference

Once the CountDownLatch is opened, it cannot be closed again. The await method will become invalid as long as it has been called enough times.

Cyclicbarriers occur in cycles, and when the last thread reaches the barrier, the barrier count is reset first, and the barrier starts blocking again.

Second difference

“CountDownLatch” is a counter that allows each thread to latch as it comes in. During this period, no thread is blocked, and the external waiting thread is awakened when the specified number of threads is reached. In other words, there are one or more external threads waiting for a certain number of threads to be fulfilled before they can continue executing. This activates the continuation of the current external thread.

A CyclicBarrier acts like a barrier, blocking one thread at a time until a specified number of threads are blocked, then activating them all at once, like a 100-meter dash.

The last

Well, the above is our Java package below the better use of three tool classes, the first two of the underlying implementation almost completely rely on the principle of explicit lock method, the latter is the use of explicit lock condition variables to rebuild the wheel, are very good tools!

In addition to this, we have covered the whole topic of concurrency, the basic core things, a total of 14 articles, from the basic concept of threads, to the principle of locking, thread pool, and asynchronous tasks, I think the summary is detailed enough, do you know how much?

It doesn’t matter if you can’t remember, I have also provided you with a summary of the mind map, listing the above basic content, you can review against, but also welcome your private message to discuss and explore me.

How to get it: reply “concurrent” on my official account or go to my Github to download it.

Ps: I also want to have a holiday, wish everyone a happy New Year, the Spring Festival period will not be more text, after the festival we will open a new chapter, system summary “database” related technology and principle, please pay attention to!

Focus on the public not getting lost, a programmer who loves to share.
Public number reply “1024” add the author wechat together to discuss learning!
All the case code materials used in each article are uploaded to my personal Github
Github.com/SingleYam/o…
Welcome to step on it!