Concurrent Programming|The "synchronized" keyword explanation that even Xiaobai can understand, the interviewer hello!

I believe that most students who have studied concurrent programming-related courses have come into contact with synchronized. It has always existed as a veteran in concurrent programming. By using synchronized, we can ensure that the programs we write can be executed according to our expectations in multiple threads. Students who have used it must all know that this keyword is very "cumbersome" and consumes cpu resources, but it has been optimized in jdk1.6, we will start to learn how to use it and how to use it in jdk1.6. What optimizations did he make

What are the ways to use synchronized?

  • Ordinary synchronization method, the lock is the current instance object
  • Static synchronization method, the lock is the class object of the current class
  • Synchronize the code block, lock things in synchronized brackets
The synchronization code block is implemented through monitorenter and monitorexit. They are placed at the beginning and end of the synchronization code block. Of course, this is inserted by the compiler for us.

How does the jvm identify that the thread has acquired the lock? This has to talk about the java object header

Store the hashcode or lock information of the object Pointer to object type data Array length (if the current object is an array)
Mark Word Class Metadata Address Array length
The above is the basic structure of the object header. The state of the lock is also stored in Mark Word. In jdk1.6, in order to reduce the performance consumption caused by the synchronized acquisition and release of the lock, the state of the lock in Mark Word is changed by `No lock state It is composed of ``biased locks,'' lightweight locks, and heavyweight locks. The level of the lock is higher than that of the first level.

Note: The lock can be upgraded but not downgraded

What is a biased lock?

The author of hotspot found that locks do not compete in most cases and are always acquired by the same thread. In order to make it cheaper for threads to acquire locks, a biased lock is introduced: when a thread acquires a lock and enters the synchronization code After the block, the thread ID of the current thread will be recorded in the current lock object header. When you enter the code block again later, you only need to determine whether the thread ID in the lock object header is yourself. If it is, you no longer need to lock by Cas. And unlock, otherwise you need to get it again.
  • Obtaining biased locks

    1. Before thread A enters the critical point, judge whether there is a bias lock pointing to the thread in the Mark Word in the object header. If there is, the lock is directly acquired and enters the critical area. If it does not exist, the next step is executed
    2. Mark word's bias lock indicates whether the bit is set to 1 (currently it is a bias lock), if not, use CAS competition lock, otherwise
    3. Use CAS to point the bias lock of the object header to the current thread
  • Revocation of bias lock

    1. Lock revocation will only happen during lock contention and there is no bytecode currently executing
    2. Suspend the thread that owns the biased lock
    3. Check whether the process with the biased lock is alive, if it is not alive, set the object header to a lock-free state, otherwise
    4. If the thread has been alive, the stack with the biased lock will be executed, the lock record in the stack and the Mark word of the object header will either be biased to other threads again, or return to a lock-free state, and finally wake up the suspended thread
  • Turn off biased locks
    Biased locks are enabled by default in jdk. If you are sure that lock competition will occur in your thread, then you can use the following command to turn off biased locks
    -XX: BiasedLockingStartupDelay = 0;

Lightweight lock

  • Lightweight lock lock

    1. Before the thread executes the synchronization code block, the JVM will create a space for storing the lock record in the current stack frame, and copy the Mark Word content of the lock object header to the lock record space just created. This step is called "Displaced Mark Word" ,
    2. Then the current thread tries to use CAS to replace the Mark Word in the object header with a memory address pointing to the current lock record space,
    3. If the replacement is successful, the lock is successfully acquired, otherwise it means that other threads are competing for the lock, then
    4. Use spin to acquire the lock.
  • Lightweight lock to unlock

    1. Use the CAS operation to replace the Mark Word copied before acquiring the lock back into the lock object header. If the result is successful, it means that no competition occurs.
    2. If it fails, the lock will swell into a heavyweight lock, and the thread trying to acquire the lightweight lock using spin will be blocked
    3. The thread that owns the lightweight lock releases the lock and wakes up the waiting thread. The awakened thread competes for the lock again and accesses the critical section.

Why the lock cannot be downgraded

Because spin locks consume CPU, in order to avoid useless spin operations, especially when the thread holding the lock is blocked, once the lock is upgraded to a heavyweight lock, it will not be restored to a lightweight lock. In this state, other threads will be blocked when they try to acquire the lock. When the thread holding the lock releases the lock, the blocked thread will be awakened, and the awakened thread will compete for the lock again.

Comparison of advantages and disadvantages of locks

lock advantage Disadvantage scenes to be used
Bias lock No additional cost for locking and unlocking If there is competition between threads, additional consumption is required Only one thread scenario
Lightweight lock Competing threads will not be blocked, improving program response speed Spin operation, too long will consume too much cpu In pursuit of response time, the tasks in the synchronization block are executed quickly and will not be blocked for a long time
Heavyweight lock Thread competition does not use spin and does not consume too much CPU Thread blocking, slow response time Pursuit of throughput, long execution time of synchronized blocks

Insert picture description here

Search on WeChat [AI Coder] Follow the handsome me and reply to [Dry goods], there will be a lot of interview materials and architect must-read books waiting for you to choose, including java basics, java concurrency, microservices, middleware, etc. The information is waiting for you.
The more you read the book without thinking, you will feel that you know a lot; and the more you read and think, the more clearly you will see that you know very little. --Voltaire

Guess you like

Origin blog.csdn.net/weixin_34311210/article/details/108331090