In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/01 Report--
This article shows you how to achieve bank deposit and withdrawal through ReentrantLock and Condition in java concurrent programming. 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.
The java.util.concurrent.locks package provides a framework interface and class for locks and wait conditions, unlike the built-in synchronization and monitor. The framework allows for more flexible use of locks and conditions, but at the expense of more difficult syntax.
The Lock interface supports lock rules with different semantics (reentrant, fair, and so on), which can be used in the context of non-blocking structures, including hand-over-hand and lock rearrangement algorithms. The main implementation is ReentrantLock.
In a similar way, the ReadWriteLock interface defines locks that readers can share and writers own. This package provides only one implementation, ReentrantReadWriteLock, because it applies to most standard usage contexts. But programmers can create their own implementations that apply to non-standard requirements.
The following is the related class diagram of the locks package:
In the past, we used the synchronized keyword when synchronizing a piece of code or objects, using the built-in features of the Java language. However, the features of synchronized also lead to problems in many scenarios, such as:
On a synchronous resource, thread A first acquires the lock of the resource and starts execution, and other threads that want to operate on the resource must wait. If thread An is in a state of long operation for some reason, such as waiting for the network, retrying again and again, and so on. Then other threads have no way to deal with their tasks in time and can only wait indefinitely. If thread A's lock is automatically released after it has been held for a period of time, can't other threads use the resource? Then there is similar to the shared lock and exclusive lock in the database, can it be applied to the application? So the introduction of Lock mechanism can solve these problems very well.
Lock provides more features than synchronized. But pay attention to the following points:
Lock is not built into the Java language. Synchronized is a keyword of the Java language, so it is a built-in feature. Lock is a class through which synchronous access can be achieved
There is a big difference between Lock and synchronized. Using synchronized does not require the user to release the lock manually. When the synchronized method or synchronized code block is executed, the system will automatically let the thread release the lock, while Lock must require the user to release the lock manually. If the lock is not released actively, it may lead to deadlock.
1. Reentrant lock ReentrantLock
When we think of locks, we generally think of synchronous locks, or Synchronized, and the reentrant lock ReentrantLock introduced here is more efficient. IBM gives an introduction to reentrant locks: a more flexible and scalable locking mechanism in JDK 5.0
Here is a brief introduction to the classification of reentrant locks: (suppose thread An acquired the lock, and now that An execution is complete, the lock is released and thread B is awakened while waiting to be woken up. However, there may be a thread C that has acquired the lock in the time that A performs the wake-up operation until B actually acquires the lock, so that the queued B cannot acquire the lock)
1) Fair lock:
Because B is waiting to be awakened, in order to ensure the principle of fairness, the fair lock will let B get the lock first.
2) unfair lock
There is no guarantee that B will get the lock object first.
The two locks only need to be distinguished when constructing the ReentrantLock object. It is a fair lock when the parameter is set to true and an unfair lock when false is set. The default constructor also creates an unfair lock.
Private Lock lock = new ReentrantLock (true); ReentrantLock's fair lock makes great sacrifices in terms of performance and effectiveness, as described in the article posted on IBM. Second, the conditional variable Condition
Condition is an interface under the java.util.concurrent.locks package, and the Condition interface describes the condition variables that may be associated with the lock. These variables are similar in usage to implicit monitors accessed by Object.wait, but provide more powerful functionality. In particular, a single Lock may be associated with multiple Condition objects. To avoid compatibility issues, the name of the Condition method is different from that in the corresponding version of Object.
Condition decomposes the Object monitor methods (wait, notify, and notifyAll) into distinct objects to provide multiple waiting set (wait-set) for each object by combining them with any Lock implementation. Lock replaces the use of synchronized methods and statements, and Condition replaces the use of Object monitor methods.
Condition (also known as conditional queues or conditional variables) provides a means for threads to stay in a suspended state (that is, "wait") under certain state conditions until notified by another thread. Because access to this shared state information occurs in different threads, it must be protected, so some form of lock is associated with the Condition.
The Condition instance is essentially bound to a lock.
The source code under the Locks package is no longer analyzed here.
Third, ReentrantLock and Condition design multi-thread deposit and withdrawal
1. When making a deposit, there can be no thread withdrawing money. When withdrawing money, there can be no thread in the deposit.
two。 When withdrawing money, the balance is greater than the withdrawal amount before the withdrawal operation can be carried out, otherwise the insufficient balance will be indicated.
3. When withdrawing money, if the amount is insufficient, block the current thread and wait for 2s (other threads may deposit the money).
If no other thread completes the deposit within 2 seconds, or if the amount is insufficient, the amount is not enough to print.
If the other deposit is sufficient, the blocking thread is notified and the withdrawal operation is completed.
/ * ordinary bank account, cannot be overdrawn * / public class MyCount {private String oid; / / account private int cash; / / account balance / / account lock. A fair lock is used here, and the suspended withdrawal thread gets the lock first instead of letting other deposit and withdrawal threads get the lock private Lock lock = new ReentrantLock (true); private Condition _ save = lock.newCondition () / / Deposit condition private Condition _ draw = lock.newCondition (); / / Deposit condition MyCount (String oid, int cash) {this.oid = oid; this.cash = cash;} / * * Deposit * @ param x Operation amount * @ param name operator * / public void saving (int x, String name) {lock.lock () / / acquire lock if (x > 0) {cash + = x; / / Deposit System.out.println (name + "Deposit" + x + ", the current balance is" + cash);} _ draw.signalAll (); / / wake up all waiting threads. Lock.unlock (); / / release lock} / * * withdrawal * @ param x Operation amount * @ param name operator * / public void drawing (int x, String name) {lock.lock (); / / acquire lock try {if (cash-x)
< 0) { System.out.println(name + "阻塞中"); _draw.await(2000,TimeUnit.MILLISECONDS); // 阻塞取款操作, await之后就隐示自动释放了lock,直到被唤醒自动获取 } if(cash-x>= 0) {cash-= x; / withdrawal System.out.println (name+ "withdrawal" + x + ", current balance is" + cash ");} else {System.out.println (current balance is insufficient, current balance is" + cash+ "withdrawal amount is" + x ") } / / Wake up all deposit operations, there is no practical use here, because there is no blocking operation _ save.signalAll () in the deposit code;} catch (InterruptedException e) {e.printStackTrace ();} finally {lock.unlock (); / / release lock}
The reentrant lock here can also be set to an unfair lock, so that blocking the withdrawal thread may be followed by other deposit and withdrawal operations.
/ * * Deposit thread class * / static class SaveThread extends Thread {private String name; / / operator private MyCount myCount; / / account private int x; / / Deposit amount SaveThread (String name, MyCount myCount, int x) {this.name = name; this.myCount = myCount; this.x = x } public void run () {myCount.saving (x, name);}} / * withdrawal thread class * / static class DrawThread extends Thread {private String name; / / operator private MyCount myCount; / / account private int x / / amount of deposit DrawThread (String name, MyCount myCount, int x) {this.name = name; this.myCount = myCount; this.x = x;} public void run () {myCount.drawing (x, name) }} public static void main (String [] args) {/ / create a concurrent access account MyCount myCount = new MyCount ("95599200901215522", 1000); / / create a thread pool ExecutorService pool = Executors.newFixedThreadPool (3); Thread T1 = new SaveThread ("S1", myCount, 1000); Thread T2 = new SaveThread ("S2", myCount, 1000) Thread T3 = new DrawThread ("D1", myCount, 12600); Thread T4 = new SaveThread ("S3", myCount, 2300); Thread T5 = new DrawThread ("D2", myCount, 2300); Thread T6 = new DrawThread ("D3", myCount, 1800); Thread T7 = new SaveThread ("S4", myCount, 1800); / / execute each thread pool.execute (T1); pool.execute (T2) Pool.execute (T3); pool.execute (T4); pool.execute (T5); pool.execute (T6); pool.execute (T7); try {Thread.sleep (3000);} catch (InterruptedException e) {e.printStackTrace ();} / close thread pool pool.shutdown ();}}
Multiple threads of deposit and withdrawal are defined in the above class, and the execution result is as follows:
S1 deposit 100, the current balance is 1100
S3 deposit 600, current balance is 1700
D2 blocking
S2 deposit 1000, current balance is 2700
D2 withdraws 2300 and the current balance is 400
D3 blocking
S4 deposit 200, current balance is 600
The balance of D3 is insufficient, the current balance is 600. the withdrawal amount is 1800
D1 blocking
D1 balance is insufficient. The current balance is 600. the withdrawal amount is 12600.
The steps are as follows:
Initialize the account with a balance of 100.
S1Magol S3 completes the deposit.
D2 withdraws, the balance is insufficient, release the lock and block the thread and enter the waiting queue.
After S2 completes the deposit operation, it wakes up the suspended thread, and D2 finishes withdrawing the money.
D3 withdraws, the balance is insufficient, release the lock and block the thread and enter the waiting queue.
After S4 finished the deposit operation, D3 was awakened, but the balance was still insufficient and D3 failed to withdraw money.
D1 withdraws money, waits for 2 seconds, and no thread wakes it up. Withdrawal fails.
It is important to note that when Condition calls the await () method, the current thread releases the lock (otherwise it is no different from Sychnize).
When the lock in the bank account is changed to an unfair lock, the result of the execution is as follows:
1 the current balance is 1100S3 deposit 1000, the current balance is 2700D3 withdrawal 1800, the current balance is 2700D3 withdrawal 1800, the current balance is 900. the withdrawal amount is 2300S4 deposit 200. the current balance is 1100D1 blockage D1 balance is insufficient, the current balance is 1100 withdrawal amount is 12600
When there is insufficient balance in D2 withdrawal, release the lock and enter the waiting state. However, when the S2 thread finished saving, it did not execute the D2 thread immediately, but was cut in line by D3.
Through the execution results, we can see the difference between the fair lock and the unfair lock. The fair lock can guarantee the priority execution of the waiting thread, but the unfair lock may be cut in line by other threads.
IV. The application of ReentrantLock and Condition in ArrayBlockingQueue
A very typical application of reentrant locks in JDK source code is BlockingQueue, which is probably known from the member variables in its source code (ArrayBlockingQueue as an example):
/ * The queued items * / final Object [] items; / * * items index for next take, poll, peek or remove * / int takeIndex; / * * items index for next put, offer, or add * / int putIndex; / * * Number of elements in the queue * / int count; / * * Concurrency control uses the classic two-condition algorithm * found in any textbook. * / * * Main lock guarding all access * / / mainly solve the thread safety problem of multi-thread access final ReentrantLock lock; / * * Condition for waiting takes * / / when adding an element, wake up the consumer thread through notEmpty (waiting for this condition) private final Condition notEmpty; / * * Condition for waiting puts * / delete the element, wake up the generation thread through notFull (waiting for this condition) private final Condition notFull
ArrayBlockingQueue is a typical producer-consumer model that holds elements through an array. In order to ensure the thread safety of adding and removing elements, reentrant locks and condition variables are added.
Reentrant locks mainly ensure that multithreading operations on blocking queues are thread-safe, and in order to wake up blocked consumers or producers automatically, conditional variables are introduced here.
When the queue is full, the Producer is blocked, and if the Customer consumes an element, the blocked Producer is automatically woken up and added to the queue.
The above two examples show the flexibility and practicality of the combination of ReentrantLock and Condition under the java.util.concurrent.locks package.
The above content is how to realize bank deposit and withdrawal through ReentrantLock and Condition in java concurrent programming. have you learned the 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.