头图

"Enough Java"-Don't be afraid of concurrency, tools come to help!

蔡不菜丶
中文

Hello everyone, I am a side dish.
A man who hopes to be about architecture ! If you also want to be the person I want to be, otherwise click on your attention and be a companion, so that Xiaocai is no longer alone!

This article mainly introduces the concurrency tools necessary for

Come here, click one to see what happened~!

The WeChat public account has been opened, , students who are not following, remember to pay attention!

As a lying brick-moving engineer, slowly moving bricks may have left you during the involute period. Bricks are a shared resource. Nowadays, every brick mover wants to pursue quality while maintaining an efficient brick moving rate. Will there be concurrency in the context of contention? The bricks you moved are calculated on someone else’s KPI . Originally, I only wanted lie flat, but I didn’t expect that would suffer such injustice when it lay flat! The salted fish, which used to be fried on one side, now has to be turned over and fried again~!

Finally, the flat brick mover decided not to lie flat anymore. He squeezed his fist, his teeth creaked, his face was yellow like wax, his lips were bitten white, and his hair was not much. With a trembling, the whole body was trembling tremblingly, and a decision was made fiercely: I must solve the concurrency problem! Let the brick moving industry operate normally~!

what? Normal operation, then the concurrency problem must be solved!

Okay, well, the atmosphere is right. At this time, the side dish is slowly coming on stage, so let's enter the topic. What are your commonly used concurrency tools to solve concurrency problems?

Several very useful concurrency tools have been provided in the JDK

  • CountDownLatch
  • CyclicBarrier
  • Semaphore
  • Exchanger

These few may be familiar to some friends, and may be a bit raw, but there is no difference between seeing the familiar but not using it and looking at the raw score. Then, through a simple explanation, we can let you use it freely in your usual development!

One, CountDownLatch

This is a concurrency tool that appears frequently in normal development. It is a down counter. It is a very practical multi-thread control tool class, this tool class is often used to control thread waiting, you can let a thread wait until the counter ends before starting execution!

We don't have to delve into the source code from the beginning, will be used first and then will be used wisely. So let’s look at a simple example

"No One Can Be Less"

Teacher Xiao Wang is a strict teacher. She is a little headstrong in class. She has to wait until all the students (10) are present before starting the class, that is, if a student is not present, the class will not start.

We have to follow the , that is, when the students 160f4c08d6328a <the total number of , this action cannot be performed in class. So how should we deal with this problem at this time?

We roll the name before class and add a if judgment. When the number of people is not satisfied, it will not enter the action of class This may be an inertial thinking, and most students will do this. Then there is a problem. Some students may just miss the call- judgment because of being late. When the 160f4c08d632b2 if executed, they will not judge again. Then the miss is a miss. Although the follow-up number is all there, the class will not start in the end. of!

Think about the improvement. If if is judged only once, if we can judge it all the time, then we can use while or for judge in a loop. The solution idea is correct, then we will lead the usage of CountDownLatch

The code is not long, but I don’t know if the result is what we want:

We can see that when 10 students have arrived, Teacher Xiao Wang started to class, but what if we are a student who did not arrive?

When the number of participants does not meet the expectations, the class will not be able to go to normal classes. It seems that our needs have been met. Then we will simulate the scene of students being late~

Still a student with a student number of 10, although he is late, the class can still go on normally!

It seems that CountDownLatch really a good tool, it simply helped us solve the problem! How did he solve it?

CountDownLatch is realized by a counter. First, set the initial value of a counter. Whenever a task is completed, the value of the counter will be reduced by 1. When the counter reaches 0 , it indicates that all tasks have been completed, and then the thread waiting on the lock can resume the task.

The first thing we can look at is the construction method of CountDownLatch

public CountDownLatch(int count) {
    if (count < 0) throw new IllegalArgumentException("count < 0");
    this.sync = new Sync(count);
}

This method requires initializing a count value, and initialize a Sync , at this time we might venture a guess, CountDownLatch bottom is by Sync achieved! Let's take a look at what is Sync ?

It can be seen that a safety variable state Sync , and its value is the counter value . There are two important methods: tryAcquireShared(int acquires) and tryReleaseShared(int releases) . So what use are these two methods?

We can first go back to the CountDownLatch class. We have already seen the role of the constructor of this class above. Next, we need to know two important methods: countDown() and await() . In our opinion, the countDown() method is used to subtract 1 count value, and the await() method is used to block the judgment whether the count value is 0 ? Then we enter the corresponding method to see how it is achieved

public void countDown() {
    sync.releaseShared(1);
}
---
public void await() throws InterruptedException {
    sync.acquireSharedInterruptibly(1);
}

These two methods call two methods in AQS : (I post the source code comments directly here, look carefully~!)

countDown()

await()

The above is CountDownLatch , then we might as well think about the usage scenarios of this tool class in real-time systems:

  1. achieves maximum parallelism

When we want to start multiple threads at the same time, to achieve maximum parallelism. For example, we want to test a singleton class. If we create a CountDownLatch with an initial value of 1, and let all threads wait on this lock, then we can easily complete the test, and only need to call countDown() once. method allows all waiting threads to resume execution at the same time

  1. Wait for n threads to complete their tasks before starting execution

Before our application is executed, make sure that certain pre-actions need to be executed

  1. Deadlock detection

We can use n threads to access shared resources, the number of threads in each test phase is different, so you can try to produce deadlock

Two, CyclicBarrier

CyclicBarrier is another multi-threaded concurrency control tool. Cyclic means cycle, which means that this counter can be repeatedly by , which is a CountDownLatch more powerful than 060f4c08d6368d. What it has to do is to block a group of threads when they reach a barrier (also called a synchronization point). Until the last thread reaches the barrier, the barrier will not open the door, and all threads intercepted by the barrier will continue to work.

That is to say CyclicBarrier is an addition timer, we also use the above "no less than one" example to illustrate how to use

The demonstration of absenteeism and lateness will no longer be demonstrated here, which is consistent with the above implementation of CountDownLatch

Here we still pay attention to two methods, one is construction method, the other is await()

We still enter the CyclicBarrier class to view the construction method

public CyclicBarrier(int parties, Runnable barrierAction) {
    if (parties <= 0) throw new IllegalArgumentException();
    this.parties = parties;
    this.count = parties;
    this.barrierCommand = barrierAction;
}

It can be found that the CountDownLatch mentioned above is still different. The construction method is only barrier point. Our focus is still to look at the await() method.

public int await() throws InterruptedException, BrokenBarrierException {
    try {
        return dowait(false, 0L);
    } catch (TimeoutException toe) {
        throw new Error(toe); // cannot happen
    }
}

To get to the bottom of it, we have to look at the dowait() method. Entering the method, we can find that the implementation is not complicated. Since the code is a bit long, we will intercept the key description

Unlike CountDownLatch , the barrier point variable is not volatile , so you don’t need to lock it to make it thread safe!

The above is CyclicBarrier ’s not go into the details~!

CyclicBarrier and CountDownLatch still somewhat similar, but we have to be clear about the difference between them:

  1. CountDownLatch: one thread (or more), wait for another N threads to complete something before executing
  2. CyclicBarrier: N threads wait for each other, all threads must wait before any thread is completed

more important: CountDownLatch is not reusable, CyclicBarrier is not reusable

Three, Semaphore

Semaphore (Semaphore) provides a more powerful control method for multithreading. Broadly speaking, the semaphore is an extension of the lock. Whether it is the internal lock synchronized or the reentry lock ReentrantLock , only one thread is allowed to access one resource at a time, while the semaphore can specify multiple threads to access a shared resource at the same time.

Let’s look at a simple example

"Grab a Parking Space"

Originally, there were 5 above-ground parking spaces in a community that could well meet the owner's parking needs, but the number of vehicles has skyrocketed in the past two years, and almost every family has one car. Naturally, the supply of parking spaces exceeds demand, so we can only follow the principle of first-come, first-served!

Then we look at the execution result:

It can be seen that the 5 parking spaces are shared resources. Only the first owner can grab the parking space. After the owner who grabs the parking space leaves, the subsequent owners can enter and get the parking space!

We extracted the attention points construction method, acquire() , release()

construction method

public Semaphore(int permits) {
    sync = new NonfairSync(permits);
}

public Semaphore(int permits, boolean fair) {
    sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}

Yes, Semaphore has two construction methods, the difference is whether to use fair lock. Then we continue to look at aquire() , release()

public void acquire() throws InterruptedException {
    sync.acquireSharedInterruptibly(1);
}

public void release() {
    sync.releaseShared(1);
}

excuse me~? front of 160f4c08d63b04. They must be familiar. Isn't the calling method the same as the CountDownLatch Yes, for these two concurrent tool classes, the bottom layer is to call the thread method of AQS If you don’t know the effect of these two methods, you can look up and view it, so I won’t repeat them here!

According to this tool class combined with the above example, we can use it in flow control! Especially for application scenarios with limited public resources, such as database connections, if there is a requirement to read data from tens of thousands of files, because they are all IO-intensive tasks, we can start dozens of threads to read concurrently, but We have to go through hard disk->memory->database, and if the number of database connections is only 10, then we must control only 10 threads at the same time to obtain the database connection to save the data, this time we can use Semaphore to do Flow control~!

Four, Exchanger

Seeing this name, I don’t know how many friends think What is this? . To be honest, the appearance rate of this tool category is really not high, and it is used less. Exchanger is a tool for inter-thread collaboration. It can be used for data exchange between threads. It provides a synchronization point where two threads can exchange data with each other. These two threads Exchanger method. If the first thread executes the exchange() method first, it will wait for the second thread to also execute the exchanger() method. When the two threads reach the synchronization point, the two threads will You can exchange data and pass the data produced by this thread to the other party.

Note here that the two threads, there is no "triangular relationship"

Before exchange() , digital thread prints numbers, letter thread prints letters, but after exchange() result is reversed:

Note: If one of the two threads does not execute the exchange() method, then it will wait for

In order to avoid this situation, we can add a timeout to exchange()

So what are the application scenarios of this tool class? We think if the production cost of creating an object in one thread's execution task is very high, and another thread task also needs to consume this object, then we can use Exchanger to help us transfer class objects. producer-consumer model can be realized!

The above are the usage and application scenarios of several concurrent tools. Of course, the application scenarios mentioned above are only a small part. Of course, more need to be explored in the development, so that can be used and used well.

At the end, the brick-moving engineer squeezed out the cigarette butt in his hand, and a long-lasting word came from the smoky air: Damn, I didn’t expect that moving a brick would not be easy these days.

Don't talk about it, don't be lazy, and be a 160f4c08d63cb1 programmer with a bragging X as an architecture~ Follow me to be a companion, so that Xiaocai is no longer alone. See you below!

看完不赞,都是坏蛋

If you work harder today, you will be able to say less begging words tomorrow!
I am Xiaocai, a man who becomes stronger with you. 💋
The WeChat public account has been opened, , students who have not followed please remember to pay attention!
阅读 294

小菜良记
搬砖爱好者 @公众号:小菜良记

搬砖爱好者

402 声望
1.7k 粉丝
0 条评论
你知道吗?

搬砖爱好者

402 声望
1.7k 粉丝
宣传栏