In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article shows you how to understand read-write locks in Java concurrency. The content is concise and easy to understand, which will definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.
ReentrantReadWriteLock
Let's explore another lock under the java.concurrent.util package, called ReentrantReadWriteLock, also known as read-write lock.
There is often a scenario in a real project:
For example, there is a shared resource called Some Data, multiple threads to operate Some Data, this operation has read and write operations, and read more and write less, then when there is no write operation, multiple threads to read Some Data will not have thread safety problems, because threads only access, there is no modification, there is no competition, so this situation should allow multiple threads to read Some Data at the same time.
But if at some point, thread X is modifying the Some Data, then other threads are not allowed to do anything with the Some Data, otherwise there will be thread safety problems.
So for this scenario of reading more and writing less, the J.U.C package provides ReentrantReadWriteLock, which contains two locks:
ReadLock: read lock, also known as shared lock
WriteLock: write lock, also known as exclusive lock
Let's take a look at what conditions are required for a thread to acquire a read lock:
There cannot be a write lock for another thread without a write request
Or there is a write request, but the calling thread is the same as the thread that holds the lock
Let's take a look at the conditions under which a thread acquires a write lock:
There must be no read locks for other threads
There must be no write locks for other threads
This is easier to understand because the write lock is exclusive.
Take a look at the following code:
Whether the public class ReentrantReadWriteLockTest {private Object data; / / cache is valid private volatile boolean cacheValid; private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock (); public void processCachedData () {rwl.readLock () .lock (); / / if the cache is invalid, update cache; otherwise use data if (! cacheValid) {/ / release the read lock rwl.readLock (). Unlock () before acquiring the write lock Rwl.writeLock () .lock (); if (! cacheValid) {/ / update data data = new Object (); cacheValid = true;} / / the lock is degraded to acquire the read lock rwl.readLock () .lock () before releasing the write lock / / release the write lock and still hold the read lock rwl.writeLock (). Unlock ();} / / use the cache /. / / release the read lock rwl.readLock (). Unlock ();}}
This code demonstrates that when getting the cache, determine whether the cache has expired, update the cache if it has expired, and use the cache if it has not expired.
You can see that we first created a read lock, judged that if the cache is valid, we can use the cache, and then release the read lock after using it. If the cache is invalid, update the cache to perform a write operation, so first release the read lock, then create a write lock, finally update the cache, and then re-acquire a read lock and release the write lock after updating the cache.
As you can see from this code, a thread can continue to acquire a read lock after it gets the write lock.
Summary
Let's summarize three features of ReentrantReadWriteLock:
Fairness
ReentrantReadWriteLock can also set whether it is fair or not during initialization.
Reentrancy
Read lock and write lock also support reentrant, for example, after a thread gets the write lock, he can still hold the write lock, or read the lock in the same way.
Lock degradation
To achieve lock degradation, you only need to acquire the write lock first, then the read lock, and finally release the write lock, and you can demote a write lock to a read lock. But there is no way to upgrade a read lock to a write lock.
Finally, let's compare ReentrantLock with ReentrantReadWriteLock.
ReentrantLock: completely mutually exclusive
ReentrantReadWriteLock: read lock sharing, write lock mutual exclusion
Therefore, in the scenario of more reading and less writing, the performance and throughput of ReentrantReadWriteLock are much better than those of ReentrantLock. But ReentrantReadWriteLock is not so obvious for scenarios that write too much.
StampedLock
We have discussed above that ReentrantReadWriteLock can greatly improve the performance in read-more-write-less scenarios. StampedLock was introduced in JDK8 and can be considered an enhanced version of ReentrantReadWriteLock.
So everyone thinks, if you have ReentrantReadWriteLock, why do you want to build a StampedLock?
This is because ReentrantReadWriteLock has problems in some specific scenarios.
For example, the "hunger" problem of writing threads.
For example: suppose that there are so many threads operating ReentrantReadWriteLock, so many threads performing read operations and few threads performing write operations. If this thread performing write operations wants to get a write lock, and ReentrantReadWriteLock's write lock is exclusive, getting a write lock means that other threads cannot have read locks or write locks, so there are a lot of read threads. In the case of a super small number of write threads, it is easy to cause the write thread hunger problem, that is, the thread performing the write operation may not be able to grab the lock, even if the fairness can be set to true, but this will lead to performance degradation.
So let's see how StampedLock plays:
First, all methods that acquire the lock return stamp, which is a number. If the stamp=0 indicates that the operation failed, the other values indicate that the operation was successful.
The second is all methods of acquiring locks, which need to take stamp as a parameter, and the value of the parameter must be the same as the stamp returned when the lock is acquired.
StampedLock provides three access modes:
Writing mode: write lock R similar to ReentrantReadWriteLock
Eding (pessimistic read mode): a read lock similar to ReentrantReadWriteLock.
Optimistic reading: optimistic reading mode
Pessimistic reading mode: writing is not allowed in the process of pessimistic reading.
Optimistic read mode: write operations are allowed during optimistic reading
Through the introduction, we can find that there are some similarities between pessimistic and optimistic reads in StampedLock and pessimistic and optimistic locks in our database.
In addition, StampedLock also provides the function of converting between read lock and write lock:
We know that ReentrantReadWriteLock write locks can be downgraded to read locks, but read locks cannot be upgraded to write locks, and StampedLock provides the ability to convert between read locks and write locks.
Finally, StampedLock is non-reentrant, which is a difference from ReentrantReadWriteLock.
Students who have read the source code may know that there is a comment in the StampedLock source code:
Let's take a look at this comment, which is a classic and demonstrates how to use StampedLock API.
Class Point {private double x, y; private final StampedLock sl = new StampedLock (); void move (double deltaX, double deltaY) {/ / an exclusively locked method / / add write locks long stamp = sl.writeLock (); try {x + = deltaX; y + = deltaY;} finally {/ / release write locks sl.unlockWrite (stamp) }} double distanceFromOrigin () {/ / A read-only method / / get an optimistic lock long stamp = sl.tryOptimisticRead (); / / suppose (XMague y) = (10Power10) / / but this is an optimistic read lock, (xQuery y) may be modified by other threads to (20Jing 20) double currentX = x, currentY = y / / so here to verify whether the write operation if (! sl.validate (stamp)) {stamp = sl.readLock (); try {currentX = x; currentY = y;} finally {sl.unlockRead (stamp);}} return Math.sqrt (currentX currentX + currentY currentY) has occurred after obtaining the optimistic lock. } void moveIfAtOrigin (double newX, double newY) {/ / upgrade / / Could instead start with optimistic, not read mode long stamp = sl.readLock (); try {while (x = 0 & & y = = 0) {long ws = sl.tryConvertToWriteLock (stamp); if (ws! = 0L) {stamp = ws; x = newX; y = newY Break;} else {sl.unlockRead (stamp); stamp = sl.writeLock ();} finally {sl.unlock (stamp);}
This class has three methods, the move method is used to move the coordinates of a point, instanceFromOrigin is used to calculate the distance from the point to the origin, and moveIfAtOrigin represents the coordinates used to move the point when the point is at the origin.
Let's analyze the source code:
The move method is a pure write operation, adding the write lock before the operation, and releasing the write lock at the end of the operation
InstanceOrigin first acquires an optimistic lock, and then starts to read the data. Let's assume that (xmemy) = (10p10), but this is an optimistic read lock, which may be modified by other threads to (20penny 20), so he will verify whether there is a write operation after obtaining the optimistic lock. If the validate result is true, it indicates that no write operation has occurred. If a write operation has occurred, it will be reread with a pessimistic read lock. Then calculate the results, and of course, finally release the lock.
Finally, the moveIfAtOrigin method is also relatively simple, mainly demonstrating how to change from pessimistic read locks to write locks.
StampedLock mainly improves performance through optimistic reading, but also solves the hunger problem of writing threads, but there are gains and losses. We can see from the sample code that StampedLock is much more complex to use than ReentrantReadWriteLock, so users have to make a choice between performance and complexity.
The above is how to understand read-write locks in Java concurrency. Have you learned any knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.