In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)05/31 Report--
This article mainly explains "how to use CAS and java optimistic lock". The content of the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "how to use CAS and java optimistic lock".
What is CAS?
CAS is CompareAndSwap, that is, compare and exchange. Why does CAS not use locks to ensure safe operation data in concurrent cases? the name actually intuitively shows the principle of CAS. The specific process of modifying data is as follows:
When manipulating data with CAS, pass both the original value of the data and the value to be modified to the method to compare whether the current target variable value is the same as the original value passed in. If it is the same, it means that the target variable has not been modified by other threads. If the target variable value is different from the original value, then it is proved that the target variable has been modified by other threads. The CAS modification failed this time.
From the above process, we can see that CAS actually ensures the safe modification of the data, but the modification may fail, that is, the modification of the target variable data is not successful. At this time, we need to cycle through the results of the CAS modification of the data, and try again if it fails.
More thoughtful students may worry about the concurrency security problems caused by the comparison and replacement operation of CAS itself, which will not happen in practical applications. Comparison and replacement is guaranteed by JDK with the help of hardware-level CAS primitives to ensure that comparison and replacement is an atomic action.
Implementation of lock-free programming with CAS
Lock-free programming refers to the safe operation of shared variables without using locks. In concurrent programming, we use all kinds of locks to ensure the security of shared variables. That is, other threads cannot operate on the same shared variable when it is guaranteed that one thread has not finished manipulating the shared variable.
The correct use of locks can ensure data security in the case of concurrency, but when the degree of concurrency is not high and the competition is not fierce, acquiring and releasing locks becomes an unnecessary performance waste. In this case, we can consider using CAS to ensure data security and realize lock-free programming.
Headache ABA problem
We have seen how CAS ensures secure manipulation of shared variables, but the above CAS operation still has its drawbacks. Assuming that the value of the shared variable accessed by the current thread is A, when thread 1 accesses the shared variable, thread 2 operates the shared variable to assign it to B, and thread 2 assigns the shared variable to An after processing its own logic. At this time, thread 1 compares the shared variable value A with the original value A, mistakenly thinking that there are no other threads to operate the shared variable, and directly returns the operation successfully. This is the ABA problem. Although most businesses do not need to care about whether other changes have been made to the shared variable, as long as the original value is consistent with the current value, there are some sensitive scenarios that not only consider that the result of the shared variable has not been modified, but also cannot accept that the shared variable has been modified by other threads. Fortunately, there is also a mature solution to the ABA problem. We add a version number to the shared variable, and the version number increases every time the shared variable is modified. What we compare in the CAS operation is not the value of the original variable, but the version number of the shared variable. The version number of the shared variable update is unique each time, so ABA problems can be avoided.
CAS Application in specific Application scenario JDK
First of all, it is not safe for multiple threads to operate on ordinary variables concurrently, and the operation result of one thread may be overwritten by other threads. For example, now we use two threads, and each thread increases the shared variable with an initial value of 1. If there is no synchronization mechanism, the result of shared variables is likely to be less than 3. That is, it is possible that both thread 1 and thread 2 read the initial value 1, thread 1 assigns it to 2, the value read by thread 2 in memory remains the same, and thread 2 increases the variable by 1 and assigns it to 2, so the end result is 2 less than the expected result 3. The self-increment operation is not an atomic operation, which leads to the unsafe operation of this shared variable. To solve this problem, JDK provides a series of atomic classes to provide corresponding atomic operations. The following is the source code of the getAndIncrement method in AtomicInteger. From the source code, let's see how to use CAS to achieve thread-safe atomic addition of integer variables.
/ * *
* atomically increase the current value by 1
*
* @ return returns the value before increment
, /
Public final int getAndIncrement () {
Return unsafe.getAndAddInt (this, valueOffset, 1)
}
You can see that getAndIncrement actually calls the getAndAddInt method of the UnSafe class to implement the atomic operation. Here is the getAndAddInt source code
/ * *
* add the given value to the target word variable and reassign it to the target variable
*
* @ param o the object where the variable to be updated is located
Memory offset value of * @ param offset variable field
* @ param delta the numeric value to increase
* @ return original value before change
* @ since 1.8
, /
Public final int getAndAddInt (Object o, long offset, int delta) {
Int v
Do {
/ / get the value of the current target variable
V = getIntVolatile (o, offset)
/ / this code is the key. Spin ensures that the addition operation will be successful.
/ / if you do not successfully continue to run the previous sentence of code, get the
/ / the value of the variable modified preemptively by the thread and tries to add it on the basis of the new value
/ / operation, which ensures the atomicity of the addition operation
} while (! compareAndSwapInt (o, offset, v, v + delta))
Return v
}
We are all familiar with locks, such as reentrant lock ReentrantLock. All kinds of locks provided by JDK basically rely on AbstractQueuedSynchronizer. When multiple threads try to acquire locks, they will wait in a queue, in which the atomicity of multi-thread queuing operation is guaranteed by CAS. The source code is as follows:
/ * *
* the underlying layer of the lock is waiting for the thread to acquire the lock to join the queue.
* @ param node thread node to be queued
* @ return precursor node of queuing node
, /
Private Node enq (final Node node) {
/ / spin waiting for the node to join the queue, and ensure that node can join the queue safely and correctly under concurrent circumstances through cas.
For (;;) {
Node t = tail
/ / when head is empty, construct dummy node to initialize head and tail
If (t = = null) {
If (compareAndSetHead (new Node ()
Tail = head
} else {
Node.prev = t
/ / if cas fails to set tail
/ / the next loop fetches the latest tail preemptively set by other threads
/ / continue trying to set up.
If (compareAndSetTail (t, node)) {
T.next = node
Return t
}
}
}
}
/ * *
* atomicity sets the tail tail node to the new queue node
, /
Private final boolean compareAndSetTail (Node expect, Node update) {
/ / you can see that the atomic operation method under the Unsafe class is called here again.
/ / if the current value of the target field (tail tail node field) is the expected value
/ / that is, if it is not preemptively modified by other threads, then the setting is successful.
/ / return true
Return unsafe.compareAndSwapObject (this, tailOffset, expect, update)
} optimistic Lock Application in Enterprise Development
In addition to the various atomic operations provided by the Uusafe class in JDK, we can use the idea of CAS to ensure the safe operation of the database in the case of concurrency. Assuming that there is a user table structure and the following data, the version field is the key to implementing optimistic locks.
Idusercoupon_numversion1 Zhu Xiaoming 00
Suppose we have a button for users to get coupons, how to prevent users from quickly clicking on the button to cause repeated coupons. We need to safely change the number of coupon_num coupons for users whose id is 1, and use the version field as the version number of CAS comparison, so as to avoid repeatedly increasing the number of coupons. The logic of comparison and replacement is realized through the WHERE condition. The sql involved is as follows:
UPDATE user
SET coupon_num = coupon_num + 1, version = version + 1
WHERE version = 0
As you can see, we query the data with id 1, and the version number is 0. When we modify the data, we can use the current version number as a condition to achieve secure modification. If the modification fails, it is proved that it has been modified by other threads, and then it depends on the specific business to decide whether to spin and try to modify it again. Here, we should pay attention to the excessive performance consumption caused by multiple thread spins in the case of fierce competition, and choose the way that is suitable for your business according to the concurrency.
Thank you for your reading, the above is the content of "how to use CAS and java optimistic locks". After the study of this article, I believe you have a deeper understanding of how to use CAS and java optimistic locks, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
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.