Use the key of the sports car to open the optimistic lock and the pessimistic lock, and the concurrent performance is extremely fast!

Foreword:

In the programming world, there are many kinds of "locks", and the locking cost and application scenarios of each type of lock may also be different. How to make good use of locks in recent years is also one of the basic qualities of programmers. In a high-concurrency scenario, if the right lock is selected, the performance of the system will be greatly improved, otherwise the performance will be reduced. Therefore, it is necessary to know the overhead of various locks and the application scenarios. Next, let's talk about these two common locks: pessimistic lock and optimistic lock.

Insert picture description here

1. What is pessimistic lock and optimistic lock

In addition, I have compiled a collection of interview questions for 20 years, including spring, concurrency, database, Redis, distributed, dubbo, JVM, microservices, etc. The following figure is a partial screenshot, if you need it , click here , the password CSDN.

Insert picture description here

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 according to 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 will block until it gets the lock ( shared

data). a time source to use one thread, other thread is blocked, and then run out the transfer of resources to other line Cheng ).

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. You can
use the version. Number mechanism and CAS algorithm implementation. Optimistic locks are suitable for multi-read applications, which can improve
throughput
. The mechanism similar to write_condition provided by databases is actually
optimistic locks provided. In Java, the atomic variable classes under the java.util.concurrent.atomic package are
implemented using CAS , an implementation of optimistic locking .

Use scenarios of two locks

From the above introduction of the two types of locks, we know that the two types of locks have their own advantages and disadvantages. One cannot be considered as 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 locking and increases the overall throughput of the system. However, if it is overwriting
, conflicts will usually occur, which will cause the upper-level application to continue retrying, which will
reduce the performance. Therefore, it is more appropriate to use pessimistic lock in the scenario of overwriting .

Two, 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 a thread A data values to be updated, read a few
will read the version at the same time the value of data, when submitting the update, if the version is just to read when
version equal value before the database when the update, or Retry the 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.

  1. Operator A reads it out (version=1) and deducts $50
    ($100-$50) from his account balance .
  2. During the operation of Operator A, Operator B also reads this user information (version=1) and deducts $20 ($100-$20) from his account balance.
  3. 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.
  4. 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-blockingSynchronization). The CAS algorithm involves three operands

  • Need to read and write memory value V
  • The value to compare 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.

Three, the 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 preparing for assignment, can we show that its value has not been modified by other threads? Obviously it is not possible, because during this time its value may be changed to another value, and then changed back to A, 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 continuously until it succeeds if it is unsuccessful). If it is unsuccessful for a long time, it will bring 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 the execution efficiency of the CPU.

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.

Fourth, CAS and synchronized use scenarios

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

Synchronized is suitable for writing more situations (more writing scenarios, more conflicts generally)

  1. 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.

  2. 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 concurrent programming in Java 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 biased 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 spinning, 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.

5. Finally:

In view of the fact that many people have been interviewing recently, I have also compiled a lot of interview topic materials here, as well as experience from other major companies. Hope it helps everyone.

The answers to the interview questions below are organized into document notes. I also sorted out some interview materials & the latest interview questions collected by some big companies in 2020 (all organized into documents, a small part of the screenshots), if necessary, you can click to enter the secret CSDN

Insert picture description here

Insert picture description here

Guess you like

Origin blog.csdn.net/banzhuanhu/article/details/109250015