In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the relevant knowledge of "the principle and advantages and disadvantages of lock implementation 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!
Locks package structure hierarchical Lock interface method signature description void lock (); acquisition lock (immortal) boolean tryLock (); acquisition lock (long time, TimeUnit unit) throws InterruptedException; acquisition lock (obsolete) void lockInterruptibly () throws InterruptedException; acquisition lock (bossy) void unlock (); release lock Condition newCondition ()
Code example:
Public class GetLockDemo {/ / fair lock / / static Lock lock = new ReentrantLock (true); / / unfair lock static Lock lock = new ReentrantLock (); public static void main (String [] args) throws InterruptedException {/ / the main thread gets the lock lock.lock () Thread thread = new Thread (()-> {/ / child thread acquires lock (immortal) System.out.println ("begain to get lock..."); lock.lock (); System.out.println ("succeed to get lock...") / the child thread acquires the lock (dip) / / boolean result = lock.tryLock (); / / System.out.println ("whether or not to get the lock:" + result) / / the child thread acquires the lock (out of date) / / try {/ / boolean result1 = lock.tryLock (5, TimeUnit.SECONDS); / / System.out.println ("whether to get the lock:" + result1) Catch (InterruptedException e) {/ / e.printStackTrace () / / the child thread acquires the lock (pushed around) / / try {/ / System.out.println ("start to get lockInterruptibly"); / / lock.lockInterruptibly () / /} catch (InterruptedException e) {/ / e.printStackTrace (); / / System.out.println ("dad asked me to stop..."); / /}}); thread.start (); Thread.sleep (10000L) Lock.unlock ();}}
Conclusion:
Lock () is the most commonly used
The lockInterruptibly () method is generally more expensive, and some implementation classes may not implement the lockInterruptible () method. Use interrupts only when you really need them, and you should see the description of the method by the implementation class before using it.
Condition
The wait (), notify (), notifyAll () methods in Object are used with synchronized to wake up one or more threads. Condition needs to be used in conjunction with Lock, providing multiple wait sets and more precise control (underlying is the park/unpark mechanism) | | collaboration method | deadlock mode 1 (lock) | deadlock mode 2 (wake up first, then suspend) | remarks | | | suspend/resume | deadlock | deadlock | discard | | wait/notify | No deadlock | deadlock | only for the synchronized keyword | | park/unpark | deadlock | No deadlock | condition | No deadlock | deadlock | | |
Condition code example:
Public class ConditionDemo {static Lock lock = new ReentrantLock (); static Condition condition = lock.newCondition (); public static void main (String [] args) throws InterruptedException {Thread thread = new Thread (()-> {lock.lock (); System.out.println ("condition.await ()"); try {condition.await () System.out.println ("here I am...");} catch (InterruptedException e) {e.printStackTrace ();} finally {lock.unlock ();}}); thread.start (); Thread.sleep (2000L); lock.lock (); condition.signalAll () Lock.unlock ();}} ReetrantLock
ReentrantLock is a reentrant lock, and the same thread can acquire the lock multiple times.
Analysis of the principle of ReentrantLock implementation
ReentrantLock needs an owner to mark which thread acquired the lock, a count to record the number of locks, and an waiters wait queue to store a list of threads that did not grab the lock.
When a thread comes in, the value of count will be judged first. If count is 0, the lock is not occupied.
Then grab the lock through the CAS operation.
If you grab the lock, the value of count will be increased by 1, and owner will be set to the reference of the current thread.
If count is not 0 and owner refers to the current thread, add 1 to the value of count
If count is not 0 and owner points to a reference that is not the current thread, put the thread in the waiting queue waiters
If the CAS fails to grab the lock, put the thread in the waiting queue waiters
When the thread finishes using the lock, it releases the lock it holds. When releasing the lock, the value of count is subtracted by 1. If the count value is 0, the owner is set to null.
If the count value is not 0, the thread waiting for the queue header will be awakened to grab the lock.
Manual implementation of the ReentrantLock code example:
Public class MyReentrantLock implements Lock {/ / Mark the count value of the number of reentrants private AtomicInteger count = new AtomicInteger (0); / / the owner of the lock private AtomicReference owner = new AtomicReference (); / / wait queue private LinkedBlockingDeque waiters = new LinkedBlockingDeque (); @ Override public boolean tryLock () {/ / determine whether the count is 0, if count! = 0, indicating that the lock is occupied int ct = count.get (); if (ct! = 0) {/ / determine whether the lock is occupied by the current thread, and if it is occupied by the current thread, do the reentry operation, count+=1 if (owner.get () = = Thread.currentThread ()) {count.set (ct + 1); return true } else {/ / if it is not occupied by the current thread, mutual exclusion, lock grab failed, return false return false }} else {/ / if count=0 indicates that the lock is not occupied, use CAS (ct 1) to grab the lock if (count.compareAndSet (ct, ct + 1)) {/ / if the lock is successfully grabbed, set owner to the reference owner.set (Thread.currentThread ()) of the current thread; return true;} else {return false }} @ Override public void lock () {/ / attempt to grab lock if (! tryLock ()) {/ / if failed, enter the waiting queue waiters.offer (Thread.currentThread ()); / / spin for (;;) {/ / determine whether it is the queue header, if it is Thread head = waiters.peek () If (head = = Thread.currentThread ()) {/ / try to grab the lock again if (! tryLock ()) {/ / if lock grabbing fails, suspend the thread and continue to wait for LockSupport.park ();} else {/ / if successful, dequeue waiters.poll (); return }} else {/ / if it is not the queue header, suspend the thread LockSupport.park ();} public boolean tryUnlock () {/ / determine whether the current thread holds the lock, if not, throw an exception if (owner.get ()! = Thread.currentThread ()) {throw new IllegalMonitorStateException () } else {/ / if yes, change count-1 if count becomes 0, unlock successfully int ct = count.get (); int nextc = ct-1; count.set (nextc); / / determine whether the count value is 0 if (nextc = = 0) {owner.compareAndSet (Thread.currentThread (), null); return true;} else {return false }} @ Override public void unlock () {/ / attempt to release the lock if (tryUnlock ()) {/ / get the queue header and wake it up if it is not null Thread thread = waiters.peek (); if (thread! = null) {LockSupport.unpark (thread);}} @ Override public boolean tryLock (long time, TimeUnit unit) throws InterruptedException {return false } @ Override public void lockInterruptibly () throws InterruptedException {} @ Override public Condition newCondition () {return null;}} synchronized VS Lock
Synchronized: advantages:
Easy to use, clear semantics, where you need it.
Provided by JVM, provides a variety of optimization schemes (lock coarsening, lock elimination, bias lock, lightweight lock)
The release of the lock is completed by the virtual machine without human intervention, which reduces the possibility of deadlock.
Disadvantages: pessimistic exclusive lock, unable to achieve advanced functions such as fair lock, read-write lock, etc.
Lock: advantages: it can realize the advanced functions of locks that cannot be realized by synchronized, such as fair locks, read-write locks, etc., and more functions can be achieved at the same time.
Disadvantages: the lock unlock needs to be released manually, which can easily lead to deadlock if not used properly.
Conclusion: both of them are reentrant locks. Synchronized can be compared to a stupid camera and provides a fixed function, while Lock can be compared to a unilateral and can adjust the required functions according to needs.
This is the end of the content of "the principle of lock implementation in Java and its advantages and disadvantages". 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.