An article takes you to learn the optimistic and pessimistic locks necessary for interviews

Insert picture description here

What is pessimistic lock and optimistic lock

The optimistic lock corresponds to the optimistic people in life who always think about things going for the better, and the pessimistic lock corresponds to the pessimists in life who always think about things going for the bad. These two kinds of people have their own advantages and disadvantages, and one kind of person is better than the other depending on the scene.

Pessimistic lock

Always assume the worst case. Every time you get the data, you think that others will modify it, so every time you get the data, you will lock it, so that others who want to get the data will block until it gets the lock (shared resource It is only used by one thread at a time, other threads are blocked, and the resources are transferred to other threads after use). Many such locking mechanisms are used in traditional relational databases, such as row locks, table locks, etc., read locks, write locks, etc., which are all locked before operations. Exclusive locks such as synchronized and ReentrantLock in Java are the realization of the pessimistic lock idea.

Optimistic lock

Always assume the best situation. Every time I get the data, I think that others will not modify it, so it will not be locked, but when updating, it will be judged whether others have updated the data during this period, and the version can be used Number mechanism and CAS algorithm implementation. Optimistic locking is suitable for multi-read application types, which can improve throughput. The mechanism similar to write_condition provided by the database is actually optimistic locking. The atomic variable class under the java.util.concurrent.atomic package in Java is implemented using CAS, an implementation of optimistic locking.

There are also various knowledge point modules to organize documents and more real interview questions from major factories. Friends in need can click the link below to get them for free

Link: 1103806531 Password: CSDN

Insert picture description here

Use scenarios of two locks

From the above introduction of the two locks, we know that the two locks have their own advantages and disadvantages. One should not be considered better than the other. For example, optimistic locks are suitable for less writes (read more scenarios), that is, conflicts are true. When this happens rarely, this saves the overhead of the lock and increases the overall throughput of the system. However, if it is over-write, conflicts will usually occur frequently, which will cause the upper-level application to constantly retry, which will reduce the performance, so it is more appropriate to use pessimistic lock in the scenario of over-write.

Two common implementations of optimistic locking

Optimistic locking is generally implemented using the version number mechanism or CAS algorithm.

1. Version number mechanism

Generally, a data version number version field is added to the data table to indicate the number of times the data has been modified. When the data is modified, the version value will increase by one. When thread A wants to update the data value, it will also read the version value while reading the data. When submitting the update, if the version value read just now is equal to the version value in the current database, it will update, otherwise try again Update operation until the update is successful.

Give a simple example:

Assuming that there is a version field in the account information table in the database, the current value is 1; and the current account balance field (balance) is $100.

Operator A reads it out (version=1) and deducts $50 ($100-$50) from his account balance.
During the operation of operator A, operator B also reads this user information (version=1 ), and deducts $20 ($100-$20) from his account balance.
Operator A completes the modification work, adds one to the data version number (version=2 ), and submits it to the database for update along with the account deduction balance (balance=$50 ). At this time, because the submitted data version is greater than the current version of the database record, the data is Update, the database record version is updated to 2.
Operator B completed the operation and also increased the version number by one (version=2) and tried to submit data to the database (balance=$80 ), but at this time, when comparing the database record version, it was found that the version number of the data submitted by operator B was 2. , The current version of the database record is also 2, which does not meet the optimistic locking strategy of "the submitted version must be greater than the current version of the record to perform the update". Therefore, the submission of operator B is rejected.

In this way, it is avoided that operator B overwrites the operation result of operator A with the result of old data modification based on version=1.

2. CAS algorithm

Namely compare and swap (compare and swap), is a well-known lock-free algorithm. Lock-free programming, that is, to achieve variable synchronization between multiple threads without using locks, that is, to achieve variable synchronization without threads being blocked, so it is also called non-blocking synchronization (Non-blocking Synchronization).

The CAS algorithm involves three operands

  • Need to read and write memory value V
  • Value to be compared A
  • New value to be written B

If and only if the value of V is equal to A, CAS atomically updates the value of V with the new value B, otherwise no operation will be performed (comparison and replacement are an atomic operation). Under normal circumstances, it is a spin operation, that is, constant retry.

Disadvantages of optimistic locking

ABA problem is a common problem with optimistic locking

1 ABA problem

If a variable V is the value of A when it is first read, and it is checked that it is still the value of A when it is ready to be assigned, can we show that its value has not been modified by other threads? Obviously it can't, because during this time its value may be changed to another value, and then changed back to A, then the CAS operation will mistakenly believe that it has never been modified. This problem is called the "ABA" problem of CAS operation.

The AtomicStampedReference class after JDK 1.5 provides this capability. The compareAndSet method first checks whether the current reference is equal to the expected reference and whether the current flag is equal to the expected flag. If all are equal, the reference and the flag are atomically The value is set to the given update value.

2 Long cycle time and high overhead

Spin CAS (that is, it will execute in a loop until it is successful) if it is unsuccessful for a long time, it will bring a very large execution overhead to the CPU. If the JVM can support the pause instruction provided by the processor, then the efficiency will be improved. The pause instruction has two functions. First, it can delay the de-pipeline execution of instructions so that the CPU will not consume too much execution resources. The delay time depends on the specific implementation version, and the delay time is zero on some processors. Second, it can avoid the CPU pipeline flush caused by memory order violation when exiting the loop, thereby improving CPU execution efficiency.

3 can only guarantee the atomic operation of a shared variable

CAS is only valid for a single shared variable. CAS is invalid when the operation involves multiple shared variables. But since JDK 1.5, the AtomicReference class is provided to ensure the atomicity between referenced objects. You can put multiple variables in one object for CAS operations. So we can use locks or use the AtomicReference class to share multiple shared variables Merge into a shared variable to operate.

Use scenarios of CAS and synchronized

Simply put, CAS is suitable for less writes (more read scenarios, generally less conflicts), synchronized is suitable for more writes (more write scenarios, generally more conflicts)

In the case of less resource competition (light thread conflicts), the use of synchronized synchronization locks for thread blocking and wake-up switching, as well as switching operations between user mode and kernel mode wastes cpu resources; CAS is based on hardware and does not need to enter the kernel. There is no need to switch threads, and the chance of operating spin is less, so higher performance can be obtained.
In the case of serious resource competition (serious thread conflict), the probability of CAS spinning is relatively large, which wastes more CPU resources and is less efficient than synchronized.

Supplement: The synchronized keyword in the field of Java concurrent programming has always been a veteran role. A long time ago, many people would call it a "heavyweight lock". However, after JavaSE 1.6, it has been mainly included in order to reduce the performance consumption of acquiring and releasing locks, and the introduction of bias locks and lightweight locks, as well as various other optimizations, has become less important in some cases. . The underlying implementation of synchronized mainly relies on Lock-Free queues. The basic idea is to block after spin and continue to compete for locks after competitive switching, which slightly sacrifices fairness, but achieves high throughput. In the case of fewer thread conflicts, performance similar to CAS can be obtained; and in the case of severe thread conflicts, the performance is much higher than CAS.

to sum up

Due to time constraints, it is not written in detail. Friends who need the full version can click the link below to get it for free

Link: 1103806531 Password: CSDN

Insert picture description here
Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_48655626/article/details/109097217