In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the knowledge of "ReetrantLock and locking in java". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
Java is mainly divided into two types of locks, one is synchronized keyword modified lock, the other is J.U.C. The lock provided. The core lock in J.U.C is ReentrantLock.
Difference between ReentrantLock (reentrant lock) and synchronized
Reentrancy
For the implementation of locks, the synchronized keyword is implemented by JVM, while ReentrantLock is implemented by JDK. What's the difference between the two? To put it bluntly, it is similar to the difference between the operating system to control the implementation and the user to tap the code. The synchronized implementation depends on JVM, and it is difficult to find the source code, while ReentrantLock can be achieved by reading the source code.
Performance differences, since the introduction of synchronized bias lock, lightweight lock (spin lock) performance is similar, the official recommendation to use synchronized.
Functional differences, synchronized is more convenient to use, by the compiler to ensure locking and release, while ReentrantLock needs to manually declare locking and releasing locks.
Unique features of ReentrantLock:
You can specify a fair or unfair lock, while synchronized can only be an unfair lock. Fair lock: the thread that waits first acquires the lock first.
Provides a Condition class that can be grouped to wake up threads that need to be awakened. Not like synchronized, random.
Provides a mechanism for interrupting threads waiting for locks, lock.lockInterruptibly (). ReentrantLock is a kind of spin lock, which can be locked by calling CAS operation looply. its performance is better because it avoids the blocking state that makes the thread enter the kernel state, and tries every means to prevent the thread from entering the kernel blocking state, which is the key for us to analyze and understand the lock design.
Working with scen
You can use ReentrantLock if you need features unique to ReentrantLock. In other cases, you can choose whether to use ReentrantLock or synchronized based on performance.
ReentrantLock can do everything synchronized can do, but synchronize can't necessarily do what ReentrantLock can do, and ReentrantLock doesn't have to be poor in terms of performance. So should we abandon synchronize? Of course, no, the classes under java.util.current.lock are generally used for advanced users and tools in advanced situations. Generally speaking, unless there is a clear need for an advanced feature of lock or there is clear evidence that synchronization has become a bottleneck in scalability under certain circumstances, it is recommended to continue to use synchronized.
Even for these advanced locking classes, synchronized still has some advantages, such as it is impossible to forget to release the lock when using synchronized, and jvm will do these things for you when you exit the synchronize block, otherwise it is difficult to find out the cause of the deadlock once you forget to release the lock, so junior developers are not recommended to use lock.
In addition, when jvm uses synchronized to manage lock requests and releases, jvm can include locking information when generating thread dumps, which are valuable for debugging because they can identify the source of deadlocks or other abnormal behavior. The lock class is just a normal class, jvm doesn't know which thread owns the lock object, and almost every developer is familiar with synchronized, can work in all versions of jvm, and can be implemented using synchronized in most usage scenarios.
@ Slf4jpublic class LockExample2 {/ / Total number of requests public static int clientTotal = 5000; / / number of threads executing concurrently public static int threadTotal = 200; public static int count = 0; private final static Lock lock = new ReentrantLock (); public static void main (String [] args) throws InterruptedException {/ / thread pool ExecutorService executorService = Executors.newCachedThreadPool (); / / define semaphore final Semaphore semaphore = new Semaphore (threadTotal) / / define counter final CountDownLatch countDownLatch = new CountDownLatch (clientTotal); for (int I = 0; I
< clientTotal; i++) { executorService.execute(() ->{try {semaphore.acquire (); add (); semaphore.release ();} catch (InterruptedException e) {log.error ("exception", e);} countDownLatch.countDown ();}) } countDownLatch.await (); executorService.shutdown (); log.info ("count: {}", count);} public static void add () {lock.lock (); try {count++;} finally {lock.unlock ();}} ReentrantReadWriteLock@Slf4jpublic class LockExample3 {private final Map map = new TreeMap () Private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock (); private final Lock readLock = lock.readLock (); private final Lock writeLock = lock.writeLock (); public Data get (String key) {readLock.lock (); try {return map.get (key);} finally {readLock.unlock ();}} public Set getAllKeys () {readLock.lock () Try {return map.keySet ();} finally {readLock.unlock ();}} public Data put (String key, Data value) {writeLock.lock (); try {return map.put (key, value);} finally {writeLock.unlock ();}} class Data {}}
Write.lock () ensures that writes only occur when there is no read lock, does more about data synchronization, and uses pessimistic reads, that is, if there is a write lock, no read lock is allowed to remain, ensuring that everything else is done at the time of writing. In this way, there is a problem that when there are more reads and few writes, calling the put method in the above example will encounter hunger (the write lock has always wanted to execute, but the read lock is always there, resulting in the write lock never being executed and waiting)
StampedLock
There are three modes of stampedLock control lock, namely, write, read and optimistic read. StampedLock consists of two modules: version and mode, which returns a number (ticket stamp). The corresponding access is represented and controlled by the corresponding lock state, and the number 0 indicates that no write lock is accessed. Read lock is divided into optimistic lock and pessimistic lock, optimistic lock is when there are many cases of reading and writing, it can be considered that the probability of reading and writing at the same time is very small, so the use of completely pessimistic locking is not pessimistic. the program can read the data whether to get write execution changes, and then take follow-up measures, this small improvement can greatly improve the throughput of the program.
@ Slf4jpublic class LockExample4 {/ / Total number of requests public static int clientTotal = 5000; / / number of threads executing concurrently public static int threadTotal = 200; public static int count = 0; private final static StampedLock lock = new StampedLock (); public static void main (String [] args) throws InterruptedException {/ / thread pool ExecutorService executorService = Executors.newCachedThreadPool (); / / define semaphore final Semaphore semaphore = new Semaphore (threadTotal) / / define counter final CountDownLatch countDownLatch = new CountDownLatch (clientTotal); for (int I = 0; I
< clientTotal; i++) { executorService.execute(() ->{try {semaphore.acquire (); add (); semaphore.release ();} catch (InterruptedException e) {log.error ("exception", e);} countDownLatch.countDown ();}) } countDownLatch.await (); executorService.shutdown (); log.info ("count: {}", count);} public static void add () {long stamp = lock.writeLock (); try {count++;} finally {lock.unlock (stamp);} Summary
Synchronized: implemented at the jvm level, you can not only monitor the lock of synchronized through some monitoring tools, but also release the lock when an exception occurs during code execution, and jvm will automatically lock and unlock it.
ReentrantLock, ReentrantReadWriteLock, StampedLock: all are locks at the object level. To ensure that the lock will be released, it is safer to put the unlock operation in the finally. StampedLock has a huge improvement in throughput, especially in scenarios where there are a lot of read threads.
So how do we choose which lock to use?
Synchronized is a good universal lock implementation when there are only a small number of competitors.
There are many competitors, and the growth trend of competitors can be predicted. ReentrantLock is a good universal lock implementation.
When we use locks, we don't look at which locks are used at an advanced level. The most important thing is that it is suitable for you to use the scene.
It is important to note that synchronized does not cause a deadlock and jvm will automatically unlock it. Other Lock may cause deadlocks if they are not used properly, and may fail to perform unlock operations in some cases.
This is the end of the content of "ReetrantLock and Lock in java". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
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.