With the vigorous development of the Internet, more and more Internet companies are facing concurrent security problems caused by the expansion of user volume. This article focuses on several common locking mechanisms in Java concurrency.
1. Positive lock
Biased lock is a lock optimization mechanism proposed by JDK1.6. The core idea is that if the program does not compete, the thread synchronization operation that has previously obtained the lock will be cancelled. That is to say, if a lock is acquired by a thread, it enters bias mode. When the thread requests the lock again, there is no need to perform relevant synchronization operations, thereby saving operation time. If other threads make lock requests in between, the lock exits bias mode. Using -XX:+UseBiasedLocking in JVM
package jvmProject;import java.util.List;import java.util.Vector;public class Biased { public static List<Integer> numberList = new Vector<Integer>(); public static void main(String[] args) { long begin = System.currentTimeMillis(); int count = 0; int startnum = 0; while(count<10000000){ numberList.add(startnum); startnum+=2; count++; } long end = System.currentTimeMillis(); System.out.println(end-begin); }}Initialize a Vector, add 100,000,000 Integer objects to it, and then output the time difference. This is used to test the performance of biased locks. As for why you should use Vector instead of ArrayList?
Because ArrayList is thread-insecure, Vector is thread-safe. This may not be specific enough, you can look at the source code.
Almost all operations in Vector are sychronized, while ArrayList does not, so Vector is thread-safe.
Next, let’s test how much impact the opening of biased locks and not opening biased locks have on program performance.
Configure the JVM startup (turn on bias lock) parameters to:
Configure the JVM startup (close bias lock) parameters to:
Perfect! The running time of the program that enables biased lock is significantly shorter. It has certain advantages to enable biased locks than to not enable biased locks. The synchronization method of operating an object in a single thread. In fact, it can also be understood in this way. When there is only one thread operating a Vector object with a synchronization method, the operation on the Vector will be converted into an operation on the ArrayList.
The biased lock does not have a strong optimization effect when the lock is competitive, because a large amount of competition will cause the thread holding the lock to switch continuously, and it is difficult for the lock to remain in the biased mode. At this time, using the biased lock not only does not achieve performance optimization, but may reduce the performance of the system. Therefore, in the case of fierce competition, you can try to use it.
-XX:-UseBiastedLocking parameter disables bias locking.
2. Lightweight lock
If the biased lock fails, the Java virtual machine will ask the thread to apply for a lightweight lock. The lightweight lock is implemented inside the virtual machine and is implemented using an object that becomes a BasicObjectLock, which is composed of a BasicLock object and a Java object pointer holding the lock. BasicObjectLock object is placed in Java stack frame. The displayed_header field is also maintained inside the BasicLock object, which is used to back up the Mark Word of the object's header.
When a thread holds an object's lock, the object's header Mark Word information is as follows
[ptr |00] locked
The two bits at the end are 00, and the entire Mark Word is a pointer to the BasicLock object. Since the BasicObjectLock object is in the thread stack, the pointer must point to the thread stack space that holds the lock. When it is necessary to determine whether a thread holds the object, it is only necessary to simply determine whether the pointer of the object header is within the stack address range of the current thread. At the same time, the displayed_header of the BasicLock object backs up the Mark word content of the original object, and the obj field of the BasicObjectLock object points to the head of the object holding the lock.
3. Heavyweight lock
When the lightweight lock fails, the virtual machine will use the heavyweight lock. When using heavyweight locks, the object's Mark Word is as follows:
[ptr |10] monitor
During operation, the thread may be suspended at the operating system level. If so, the cost of switching and calling between threads will be greatly increased.
4. Spin lock
A spin lock can make the thread not suspended when it has not obtained the lock, but instead switch to execute an empty loop (that is, the so-called spin, which means executing the empty loop itself). If the thread can obtain the lock after several empty loops, it will continue to execute. If the thread still cannot obtain the lock, it will be suspended.
After using spin lock, the chance of thread being suspended is relatively reduced, and the consistency of thread execution is relatively enhanced. Therefore, it has certain positive significance for concurrent threads that are not very competitive with locks and have a very short time. However, for concurrent programs that are fiercely competitive with locks and single-threaded locks occupy a long time, the spin lock often resolutely cannot obtain the corresponding lock after spin waiting. This not only wastes CPU time, but also inevitably has the suspended operation in the end, but also wastes the system resources.
In JDK1.6, the Java virtual machine provides the -XX:+UseSpinning parameter to enable the spin lock, and uses the -XX:PreBlockSpin parameter to set the number of times the spin lock waits.
Starting from JDK 1.7, the parameters of the spin lock are cancelled. The virtual machine no longer supports the user-configured spin lock. The spin lock will always be executed, and the number of spin locks is automatically adjusted by the virtual machine.