The pessimist and the optimist way of doing things is completely different, the pessimist’s outlook on life is one thing I must be 100 percent complete control will do, otherwise it will be thought that this thing will go wrong; The optimist’s outlook on life is on the contrary. No matter what the final result is, he will try to do it first, even if the last is not successful. This is the difference between pessimistic lock and optimistic lock. Pessimistic lock will lock the whole object as its own before it does operations, while optimistic lock does not acquire the lock directly, and then decides whether to update data through certain detection means. This section takes a closer look at optimistic locking.

The former Synchronized mutex belongs to the pessimistic lock, which has an obvious disadvantage. It is locked regardless of whether there is competition for data storage. With the increase of concurrency, and if the lock time is relatively long, its performance cost will become very large. Is there a way around this? The answer is optimistic locking based on conflict detection. This mode, there is no so-called lock concept, each thread is directly to perform the operation, first calculate after the completion of testing whether to compete with other threads share data, if not for this operation is successful, if there is a Shared data competition may be constantly to perform operations and inspection, until success, can be called CAS spin.

The core algorithm of optimistic lock is CAS (Compare and Swap), which involves three operands: memory value, expected value and new value. Change the memory value to the new value if and only if the expected value is equal to the memory value. The logic of this process is to first check whether the value of a block of memory is the same as the value when I read it before. If it is not the same, it means that the memory value has been changed by another thread during the period, and this operation is abandoned. Otherwise, it means that no other thread operates on this memory value during the period, and you can set the new value to this block of memory. As shown in figure, there are two threads may be almost at the same time of a memory operations, thread 2 first reading a memory value as expected, thread 2 when performing a somewhere decided to set the new value to the memory block, if the thread a modified the memory block during this period, can be detected by CAS namely, if test no problem, thread 2 gives a new value to the memory block.

public class AtomicInt {
    private volatile int value; 
    public final int get() {
        return value;
    }
	
	public final int getAndIncrement() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                returncurrent; }} Public final Boolean compareAndSet(int expect, int update) {Unsafe class provides the hardware-level compareAndSwapInt method; }}Copy the code

The most important method is the getAndIncrement method, which implements the spin based on CAS. Optimistic locking avoids the phenomenon of pessimistic locking monopolizing objects and improves concurrency performance, but it also has disadvantages:

  1. Viewing locking can only guarantee atomic operations on a shared variable. In the example above, only the atomicity of the value variable can be guaranteed during the spin process. In this case, if one or more variables are added, optimistic locking will become difficult, but mutex can be easily solved, regardless of the number of objects and the size of objects.
  2. Spinning for long periods of time can result in high overhead. If the CAS spins unsuccessfully for a long period of time, it incurs a lot of CPU overhead.
  3. ABA problem. CAS is the core idea by comparing memory value and expected values are the same and determine whether memory value be changed, but the judgment logic is not strict, if memory value turns out to be A, was A thread to B, then be changed to A, the CAS think this memory value did not change, but in fact is by other threads to mend, This situation has a significant impact on the results of operations in scenarios that depend on process values. The idea is to introduce a version number, incrementing the version number each time a variable is updated.

Optimistic locking is an improvement over pessimistic locking, and although it has its drawbacks, it has become a major means of improving concurrency performance, and cas-based optimistic locking is also used heavily in the JDK.

————- Recommended reading ————

My 2017 article summary – Machine learning

My 2017 article summary – Java and Middleware

My 2017 article summary – Deep learning

My 2017 article summary — JDK source code article

My 2017 article summary – Natural Language Processing

My 2017 Article Round-up — Java Concurrent Article


Talk to me, ask me questions:

The public menu has been divided into “distributed”, “machine learning”, “deep learning”, “NLP”, “Java depth”, “Java concurrent core”, “JDK source”, “Tomcat kernel” and so on, there may be a suitable for your appetite.

Why to write “Analysis of Tomcat Kernel Design”

Welcome to: