Home  >  Article  >  Java  >  How to optimize Java locks

How to optimize Java locks

PHPz
PHPzforward
2023-05-16 08:16:051216browse

Lock optimization

The lock optimization here mainly refers to the optimization of synchronized by JVM.

Spin lock

Mutex synchronization into the blocking state is very expensive and should be avoided as much as possible. In many applications, shared data is locked for only a short period of time. The idea of ​​a spin lock is to allow a thread to perform a busy loop (spin) for a period of time when requesting a shared data lock. If the lock can be obtained during this period, it can avoid entering the blocking state.

Although spin lock can avoid entering the blocking state and reduce overhead, it requires a busy loop operation to occupy CPU time. It is only suitable for scenarios where the lock state of shared data is very short.

Adaptive spin locks were introduced in JDK 1.6. Adaptive means that the number of spins is no longer fixed, but is determined by the previous number of spins on the same lock and the status of the lock owner.

Lock elimination

Lock elimination refers to the elimination of locks on shared data that are detected to be unlikely to have competition.

Lock elimination is mainly supported by escape analysis. If the shared data on the heap cannot escape and be accessed by other threads, then they can be treated as private data, and their locks can be eliminated.

For some code that does not appear to be locked, a lot of locks are actually implicitly added. For example, the following string splicing code implicitly adds a lock:

public static String concatString(String s1, String s2, String s3) { return s1 s2 s3; }

String is an immutable class, and the compiler will automatically optimize the splicing of String. Before JDK 1.5, it will be converted to a continuous append() operation of StringBuffer object:

public static String concatString(String s1, String s2, String s3) { StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); sb.append(s3); return sb.toString() ; }

There is a synchronized block in every append() method. The virtual machine observes the variable sb and quickly discovers that its dynamic scope is restricted inside the concatString() method. That is, any reference to sb never escapes outside the concatString() method and is inaccessible to other threads, so it can be eliminated.

Lock roughening

If a series of consecutive operations repeatedly lock and unlock the same object, frequent locking operations will cause performance loss.

The consecutive append() methods in the sample code in the previous section fall into this category. If the virtual machine detects that the same object is locked by such a series of fragmented operations, it will expand (coarsen) the locking range to the outside of the entire operation sequence. The sample code in the previous section is extended from before the first append() operation to after the last append() operation, so that it only needs to be locked once.

​Lightweight lock

JDK 1.6 introduced biased locks and lightweight locks, allowing locks to have four states: unlocked, biased, lightweight locked and heavyweight locked. inflated).

Heavyweight locks are also commonly referred to as synchronized object locks.

The following is the memory layout of the HotSpot virtual machine object header. These data are called Mark Word. The tag bits correspond to five states, which are given in the state table on the right. In addition to the marked for gc state, the other four states have been introduced previously.

The left side of the figure below is the virtual machine stack of a thread. There is a part of the area called Lock Record, which is created during the running process of lightweight lock and is used to store the Mark Word of the lock object. On the right is a lock object, which contains Mark Word and other information.

Compared with traditional heavyweight locks, lightweight locks use CAS operations to avoid the overhead of heavyweight locks using mutexes. For most locks, there is no competition during the entire synchronization cycle, so there is no need to use mutexes for synchronization. You can first use CAS operations for synchronization. If CAS fails, use mutexes instead. to synchronize.

When trying to acquire a lock object, if the lock object is marked as 0 01, it means that the lock object is in the unlocked state. At this time, the virtual machine creates a Lock Record in the virtual machine stack of the current thread, and then uses the CAS operation to update the Mark Word of the object to the Lock Record pointer. If the CAS operation succeeds, the thread acquires the lock on the object, and the object's Mark Word lock tag changes to 00, indicating that the object is in a lightweight lock state.

If the CAS operation fails, the virtual machine will first check whether the object's Mark Word points to the virtual machine stack of the current thread. If so, it means that the current thread already owns the lock object, and then it can directly enter the synchronization block to continue execution. Otherwise, it means this The lock object has been preempted by other threads. If more than two threads compete for the same lock, the lightweight lock is no longer effective and needs to be expanded into a heavyweight lock.

Bias lock

The idea of ​​biased lock is to favor the first thread to acquire the lock object. This thread will no longer need to perform synchronization operations after acquiring the lock, and even CAS operations are no longer needed.

When the lock object is acquired by the thread for the first time, it enters the biased state and is marked as 1 01. At the same time, use the CAS operation to record the thread ID into Mark Word. If the CAS operation is successful, this thread does not need to perform any synchronization operations every time it enters the synchronization block related to this lock.

When another thread tries to acquire this lock object, the bias state ends. At this time, the bias (Revoke Bias) is revoked and returned to the unlocked state or lightweight lock state.

The above is the detailed content of How to optimize Java locks. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete