Countdownlatch source code analysis of Java Concurrent series

Countdownlatch is a very useful tool class. Using it, we can intercept one or more threads and make them execute after a certain condition is ripe. It internally provides a counter. When constructing locking, the initial value of the counter must be specified, and the initial value of the counter must be greater than 0. In addition, it also provides a countdown method to operate the counter value. Each time the countdown method is called, the counter will decrease by 1. Until the counter value decreases to 0, it means that the condition is mature, and all threads blocked by calling the await method will be awakened. This is the internal mechanism of countdownlatch. It seems very simple. It is nothing more than blocking some threads to execute after reaching a certain condition. However, countdownlatch has a wide range of application scenarios. As long as your brain hole is big enough, you can use it to play all kinds of tricks. The most common application scenario is to start multiple threads to execute a task at the same time, and then count and summarize the results after all tasks are executed. The following figure dynamically demonstrates the whole process of locking and blocking threads.

The above figure shows that five threads are blocked by calling the await method, and they need to wait until the counter value is reduced to 0 to continue execution. The initial value of the counter is specified when constructing the lock, and then decreases by 1 with each call of the countdown method. The following code shows the construction method of countdownlatch.

Countdownlatch has only one constructor with parameters. You must pass in a value greater than 0 as the initial value of the counter, otherwise an error will be reported. You can see that in the constructor, you just go to a new Sync object and assign it to the member variable sync. Like other synchronization tool classes, the implementation of countdownlatch depends on AQS, which is an application under AQS sharing mode. Countdownlatch implements an internal class sync and uses it to inherit AQS, so that most of the methods provided by AQS can be used. Let's take a look at the code of the sync inner class.

You can see that the construction method of sync will set the value of synchronization status to the passed in parameter value. After that, every time the countdown method is called, the value of the synchronization state will be reduced by 1, which is the implementation principle of the counter. The two most commonly used methods when using the countdownlatch tool class are the await method and the countdown method. Calling the await method will block the current thread until the counter is 0, and calling the countdown method will reduce the value of the counter by 1 until it is 0. Let's take a look at how the await method is called.

When a thread invokes the await method, it actually invokes the acquiressaredinterruptible method of AQS. This method obtains the lock in response to thread interruption. The code of this method is also pasted above. We can see that in the acquiresharedinterruptible method, we will first call the tryacquireshared method to try to obtain the lock. We can see the logic of the tryacquireshared method rewritten in sync. The implementation logic of the method is very simple. It is to judge whether the current synchronization state is 0. If it is 0, it returns 1 to indicate that the lock can be obtained. Otherwise, it returns - 1 to indicate that the lock cannot be obtained. If the tryacquireshared method returns 1, the thread can continue to execute without waiting. If it returns - 1, the following will call the doacquiresharedinterruptible method to make the thread enter the synchronization queue and wait. This is the principle that calling the await method will block the current thread. Let's see how the countdown method wakes up the blocked thread.

You can see that the countdown method calls the releaseshared method, which is also a method in AQS. We also posted its code above. In the releaseshared method, we first call the tryrereleaseshared method to try to release the lock. The tryrereleaseshared method is an abstract method in AQS. Its specific implementation logic is in the subclass sync class. We can find this method in the sync class code posted above. If the tryrereleaseshared method returns true, it indicates that the release was successful, and false indicates that the release failed. It will return true only when the synchronization state is exactly 0 after reducing the synchronization state by 1. In other cases, it will return false. Then, when tryrereleaseshared returns true, the doreleaseshared method will be called immediately to wake up all threads in the synchronization queue. This explains why the last call to the countdown method to reduce the counter to 0 wakes up all blocked threads. These are the basic principles of countdownlatch. Let's take a look at an example of its use.

Application scenario: when playing happy landlords, you must wait for all three players to deal cards.

The operation results show that the licensing operation must be carried out after all players are admitted. We'll put the latch on line 23 Comment out await() and compare the results.

You can see in the comment out latch After await (), there is no guarantee that cards will not be dealt until all players enter.

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support programming tips.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>